Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] wifi: iwlwifi: mld: validate sta_mask before ffs() in BA session handlers
From: Junrui Luo @ 2026-04-02  6:48 UTC (permalink / raw)
  To: Miri Korenblit, Johannes Berg, Shaul Triebitz, Daniel Gabay,
	Benjamin Berg
  Cc: Anjaneyulu, Emmanuel Grumbach, linux-wireless, linux-kernel,
	Yuhao Jiang, stable, Junrui Luo

Three BA session handlers use ffs(ba_data->sta_mask) - 1 to derive a
station ID without checking that sta_mask is non-zero. When sta_mask is
zero, ffs() returns 0 and the subtraction wraps to 0xFFFFFFFF, causing
an out-of-bounds access on fw_id_to_link_sta[].

Add WARN_ON_ONCE(!ba_data->sta_mask) guards before each ffs() call,
consistent with the existing check in iwl_mld_ampdu_rx_start().

Fixes: d1e879ec600f ("wifi: iwlwifi: add iwlmld sub-driver")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/agg.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
index 3bf36f8f6874..e3627ad0321c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
@@ -64,6 +64,9 @@ static void iwl_mld_release_frames_from_notif(struct iwl_mld *mld,
 	}
 
 	/* pick any STA ID to find the pointer */
+	if (WARN_ON_ONCE(!ba_data->sta_mask))
+		goto out_unlock;
+
 	sta_id = ffs(ba_data->sta_mask) - 1;
 	link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
 	if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
@@ -166,6 +169,9 @@ void iwl_mld_del_ba(struct iwl_mld *mld, int queue,
 		goto out_unlock;
 
 	/* pick any STA ID to find the pointer */
+	if (WARN_ON_ONCE(!ba_data->sta_mask))
+		goto out_unlock;
+
 	sta_id = ffs(ba_data->sta_mask) - 1;
 	link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
 	if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
@@ -347,6 +353,9 @@ static void iwl_mld_rx_agg_session_expired(struct timer_list *t)
 	}
 
 	/* timer expired, pick any STA ID to find the pointer */
+	if (WARN_ON_ONCE(!ba_data->sta_mask))
+		goto unlock;
+
 	sta_id = ffs(ba_data->sta_mask) - 1;
 	link_sta = rcu_dereference(ba_data->mld->fw_id_to_link_sta[sta_id]);
 

---
base-commit: 7aaa8047eafd0bd628065b15757d9b48c5f9c07d
change-id: 20260402-fixes-8758bb638a7c

Best regards,
-- 
Junrui Luo <moonafterrain@outlook.com>


^ permalink raw reply related

* Re: [PATCH ath-next v5] wifi: ath12k: avoid dynamic alloc when parsing wmi tb
From: Nicolas Escande @ 2026-04-02 10:44 UTC (permalink / raw)
  To: Jeff Johnson, Nicolas Escande, ath12k; +Cc: linux-wireless
In-Reply-To: <a124d5d0-ef46-448b-b226-8642da61e0cd@oss.qualcomm.com>

On Mon Mar 30, 2026 at 9:38 PM CEST, Jeff Johnson wrote:
> On 3/30/2026 3:24 AM, Nicolas Escande wrote:
>> diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
>> index c31c47fb5a73..76060d448920 100644
>> --- a/drivers/net/wireless/ath/ath12k/core.c
>> +++ b/drivers/net/wireless/ath/ath12k/core.c
>> @@ -2258,6 +2258,7 @@ void ath12k_core_free(struct ath12k_base *ab)
>>  	timer_delete_sync(&ab->rx_replenish_retry);
>>  	destroy_workqueue(ab->workqueue_aux);
>>  	destroy_workqueue(ab->workqueue);
>> +	ath12k_wmi_free();
>
> nit:
> the order of init is ab, wq, wq_aux, wmi
> the order of free should be reversed: wmi, wq_aux, wq, ab
> which matches the init error path
Sure, I kept it as revers xmas tree because it looks nicer and doesn't change a
thing but lets keep it consistent no problem
>
>>  	kfree(ab);
>>  }
>>  
>
> other than that, this looks good to me


^ permalink raw reply

* Re: [PATCH ath-next v5] wifi: ath12k: avoid dynamic alloc when parsing wmi tb
From: Nicolas Escande @ 2026-04-02 10:47 UTC (permalink / raw)
  To: Baochen Qiang, Nicolas Escande, ath12k; +Cc: linux-wireless
In-Reply-To: <b066de0a-71bc-4d03-8ce1-c6ff22eddda1@oss.qualcomm.com>

On Tue Mar 31, 2026 at 4:44 AM CEST, Baochen Qiang wrote:
[...]
>> @@ -11239,3 +11149,30 @@ int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
>>  	dev_kfree_skb(skb);
>>  	return ret;
>>  }
>> +
>> +int ath12k_wmi_alloc(void)
>> +{
>> +	guard(mutex)(&ath12k_wmi_mutex);
>> +
>> +	if (!ath12k_wmi_tb)
>> +		ath12k_wmi_tb = __alloc_percpu(WMI_TAG_MAX * sizeof(void *),
>> +					       __alignof__(void *));
>> +	if (!ath12k_wmi_tb)
>> +		return -ENOMEM;
>
> better move the second testing inside ?
>
> 	if (!ath12k_wmi_tb) {
> 		ath12k_wmi_tb = alloc();
> 		if (!ath12k_wmi_tb)
> 			return -ENOMEM;
> 	}

I tend to prefer not over indenting when I can avoid it but ok.

>
>> +
>> +	ath12k_wmi_refcount++;
>> +	return 0;
>> +}
>> +
>> +void ath12k_wmi_free(void)
>> +{
>> +	guard(mutex)(&ath12k_wmi_mutex);
>> +
>> +	if (!WARN_ON(ath12k_wmi_refcount - 1 < 0))
>
> better to use refcount_t and its APIs?

Indeed I'm not familiar with them but I'll look into it

>
>> +		ath12k_wmi_refcount--;
>> +
>> +	if (!ath12k_wmi_refcount) {
>> +		free_percpu(ath12k_wmi_tb);
>> +		ath12k_wmi_tb = NULL;
>> +	}
>> +}

^ permalink raw reply

* [PATCH 1/1] wifi: cfg80211: wext: prevent encoding_size overflow in giwrange
From: Ren Wei @ 2026-04-02 12:10 UTC (permalink / raw)
  To: linux-wireless
  Cc: johannes, linville, kilroyd, yifanwucs, tomapufckgml, yuantan098,
	bird, enjou1224z, xuyuqiabc, n05ec
In-Reply-To: <20260402121007.339835-1-n05ec@lzu.edu.cn>

From: Yuqi Xu <xuyuqiabc@gmail.com>

cfg80211_wext_giwrange() appends one encoding_size entry for each
WLAN_CIPHER_SUITE_WEP40 and WLAN_CIPHER_SUITE_WEP104 value advertised by
the wiphy. struct iw_range only provides IW_MAX_ENCODING_SIZES slots in
encoding_size[], so duplicated WEP entries can advance num_encoding_sizes
past the end of the array and corrupt the iw_range buffer returned by
SIOCGIWRANGE.

This can happen when the wiphy cipher list contains duplicated WEP entries.

Only append encoding sizes while there is still room in the fixed-size
array. This keeps the current behaviour for normal cipher lists and
truncates oversized WEP capability lists instead of writing past the end of
the buffer.

Fixes: 2ab658f9ce21 ("cfg80211: set WE encoding size based on available ciphers")
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Co-developed-by: Yuan Tan <yuantan098@gmail.com>
Signed-off-by: Yuan Tan <yuantan098@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Yuqi Xu <xuyuqiabc@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
 net/wireless/wext-compat.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 5a70a0120343..9c5ac7da774c 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -170,13 +170,15 @@ int cfg80211_wext_giwrange(struct net_device *dev,
 			break;
 
 		case WLAN_CIPHER_SUITE_WEP40:
-			range->encoding_size[range->num_encoding_sizes++] =
-				WLAN_KEY_LEN_WEP40;
+			if (range->num_encoding_sizes < IW_MAX_ENCODING_SIZES)
+				range->encoding_size[range->num_encoding_sizes++] =
+					WLAN_KEY_LEN_WEP40;
 			break;
 
 		case WLAN_CIPHER_SUITE_WEP104:
-			range->encoding_size[range->num_encoding_sizes++] =
-				WLAN_KEY_LEN_WEP104;
+			if (range->num_encoding_sizes < IW_MAX_ENCODING_SIZES)
+				range->encoding_size[range->num_encoding_sizes++] =
+					WLAN_KEY_LEN_WEP104;
 			break;
 		}
 	}
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH v2 4/4] net/rds: Use special gfp_t format specifier
From: Allison Henderson @ 2026-04-02 17:16 UTC (permalink / raw)
  To: Brendan Jackman, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Stanislaw Gruszka,
	Alexander Potapenko, Marco Elver, Dmitry Vyukov, Andrew Morton,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: dri-devel, linux-kernel, linux-wireless, kasan-dev, linux-mm,
	netdev, linux-rdma, rds-devel
In-Reply-To: <20260326-gfp64-v2-4-d916021cecdf@google.com>

On Thu, 2026-03-26 at 12:32 +0000, Brendan Jackman wrote:
> %pGg produces nice readable output and decouples the format string from
> the size of gfp_t.
> 
> Signed-off-by: Brendan Jackman <jackmanb@google.com>
> ---
>  net/rds/tcp_recv.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c
> index 49f96ee0c40f6..ffe843ca219c7 100644
> --- a/net/rds/tcp_recv.c
> +++ b/net/rds/tcp_recv.c
> @@ -275,7 +275,7 @@ static int rds_tcp_read_sock(struct rds_conn_path *cp, gfp_t gfp)
>  	desc.count = 1; /* give more than one skb per call */
>  
>  	tcp_read_sock(sock->sk, &desc, rds_tcp_data_recv);
> -	rdsdebug("tcp_read_sock for tc %p gfp 0x%x returned %d\n", tc, gfp,
> +	rdsdebug("tcp_read_sock for tc %p gfp %pGg returned %d\n", tc, &gfp,
>  		 desc.error);
>  
>  	if (skb_queue_empty_lockless(&sock->sk->sk_receive_queue) &&
> 
This looks fine to me. Thanks Brendan!

Acked-by: Allison Henderson <achender@kernel.org>

^ permalink raw reply

* Re: [PATCH 0/6] Deprecate Legacy IP
From: Mauro Carvalho Chehab @ 2026-04-02 20:27 UTC (permalink / raw)
  To: David Woodhouse
  Cc: Fernando Fernandez Mancera, Saeed Mahameed, Leon Romanovsky,
	Tariq Toukan, Mark Bloch, Andrew Lunn, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Nikolay Aleksandrov, Ido Schimmel, Martin KaFai Lau,
	Daniel Borkmann, John Fastabend, Stanislav Fomichev,
	Alexei Starovoitov, Andrii Nakryiko, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Kuniyuki Iwashima,
	Willem de Bruijn, David Ahern, Neal Cardwell, Johannes Berg,
	Pablo Neira Ayuso, Florian Westphal, Phil Sutter, Guillaume Nault,
	Kees Cook, Alexei Lazar, Gal Pressman, Paul Moore, netdev,
	linux-rdma, linux-kernel, oss-drivers, bridge, bpf,
	linux-wireless, netfilter-devel, coreteam, torvalds,
	jon.maddog.hall
In-Reply-To: <2cb91533e22ed6cb11205dbc56b8aeedbbce0cca.camel@infradead.org>

On Wed, 01 Apr 2026 09:25:08 +0100
David Woodhouse <dwmw2@infradead.org> wrote:

> On Wed, 2026-04-01 at 10:07 +0200, Fernando Fernandez Mancera wrote:
> >  
> > 
> > Dammit, you've beaten me to it! This was my next step for 7.2.
> > 
> > Fully-endorsed-by: Fernando Fernandez Mancera <fmancera@suse.de>  
> 
> Yeah. The date notwithstanding, 

You tricked me on this April fools day...

Very funny!

> I do actually think we should do most
> of this for real.
> 
> Maybe we don't get away with the actual deprecation and the warnings on
> use *just* yet, and *maybe* we won't even get away with calling the
> config option CONFIG_LEGACY_IP, although I would genuinely like to see
> us moving consistently towards saying "Legacy IP" instead of "IPv4"
> everywhere.

IPv4 is not legacy yet... Lots of configurations, service providers
and corporations that requires the usage of VPN are IPv4 only still
today. For instance, my paid VPN provider only grants IPv4 addresses
(at least for those not using their proprietary software).

> 
> But we *should* clean up the separation of CONFIG_INET and
> CONFIG_IPV[64] and make it possible to build with either protocol
> alone.

That makes sense on my eyes.

Thanks,
Mauro

^ permalink raw reply

* Re: [PATCH ath-next] wifi: ath12k: Create symlink for each radio in a wiphy
From: Rameshkumar Sundaram @ 2026-04-03  4:51 UTC (permalink / raw)
  To: Roopni Devanathan, ath12k; +Cc: linux-wireless, Harshitha Prem
In-Reply-To: <20260402051402.3903795-1-roopni.devanathan@oss.qualcomm.com>



On 4/2/2026 10:44 AM, Roopni Devanathan wrote:
> In single-wiphy design, when more than one radio is registered as a
> single-wiphy in the mac80211 layer, the following warnings are seen:
> 
> 1. debugfs: File 'ath12k' in directory 'phy0' already present!
> 2. debugfs: File 'simulate_fw_crash' in directory 'pci-0000:57:00.0' already present!
>     debugfs: File 'device_dp_stats' in directory 'pci-01777777777777777777777:57:00.0' already present!
> 
> When more than one radio is registered as a single-wiphy, symlinks for
> all the radios are created in the same debugfs directory:
> /sys/kernel/debug/ieee80211/phyX/ath12k, resulting in warning 1. When a
> symlink is created for the first radio, since the 'ath12k' directory is
> not present, it will be created and no warning will be thrown. But when
> symlink is created for more than one radio, since the 'ath12k'
> directory was already created for symlink for radio 1, a warning is
> thrown complaining that 'ath12k' directory is already present. To resolve
> warning 1, create symlink for each radio in separate debugfs directories.
> For the first radio, the symlink will always be the 'ath12k' directory.
> This ensures that the existing directory structure is retained for
> single-wiphy and multi-wiphy architectures. In single-wiphy architecture
> with multiple radios, create symlink in separate debugfs directories
> introduced by mac80211.
> 
> Existing debugfs directory in single-wiphy architecture:
> /sys/kernel/debug/ieee80211/phyX/ath12k is a symlink to
> /sys/kernel/debug/ath12k/pci-0001:01:00.0/macY
> 
> Proposed debugfs directory in single-wiphy architecture with one radio:
> /sys/kernel/debug/ieee80211/phyX/ath12k is a symlink to
> /sys/kernel/debug/ath12k/pci-0001:01:00.0/mac0
> 
> Proposed debugfs directory in single-wiphy architecture with more than
> one radio:
> /sys/kernel/debug/ieee80211/phyX/radio0/ath12k is a symlink to
> /sys/kernel/debug/ath12k/pci-0001:01:00.0/mac0 and
> /sys/kernel/debug/ieee80211/phyX/radioY/ath12k is a symlink to
> /sys/kernel/debug/ath12k/pci-0001:01:00.0/macY
> 
> Where X is phy index and Y is radio index, seen in
> 'iw phyX info | grep Idx'. Two symlinks for the first radio are to ensure
> compatibility with the existing design. Add radio_idx inside ar, to track
> the radio index in probing order.
> 
> API ath12k_debugfs_pdev_create() that creates SoC entries is called more
> than once when hardware group starts up, resulting in warning 2. To
> resolve this warning, remove all other calls to this API and add one
> inside the ath12k_core_pdev_create(). This API carries all pdev-specific
> initializations and can conveniently hold a call to
> ath12k_debugfs_pdev_create().
> 
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
> 
> Co-developed-by: Harshitha Prem <harshitha.prem@oss.qualcomm.com>
> Signed-off-by: Harshitha Prem <harshitha.prem@oss.qualcomm.com>
> Signed-off-by: Roopni Devanathan <roopni.devanathan@oss.qualcomm.com>
> ---
>   drivers/net/wireless/ath/ath12k/core.c    |  4 ++--
>   drivers/net/wireless/ath/ath12k/core.h    |  2 ++
>   drivers/net/wireless/ath/ath12k/debugfs.c | 29 +++++++++++++++++++----
>   drivers/net/wireless/ath/ath12k/mac.c     |  2 +-
>   4 files changed, 29 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
> index c31c47fb5a73..2519e2400d58 100644
> --- a/drivers/net/wireless/ath/ath12k/core.c
> +++ b/drivers/net/wireless/ath/ath12k/core.c
> @@ -835,8 +835,6 @@ static int ath12k_core_soc_create(struct ath12k_base *ab)
>   		goto err_qmi_deinit;
>   	}
>   
> -	ath12k_debugfs_pdev_create(ab);
> -
>   	return 0;
>   
>   err_qmi_deinit:
> @@ -869,6 +867,8 @@ static int ath12k_core_pdev_create(struct ath12k_base *ab)
>   		goto err_dp_pdev_free;
>   	}
>   
> +	ath12k_debugfs_pdev_create(ab);
> +
>   	return 0;
>   
>   err_dp_pdev_free:
> diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
> index 59c193b24764..046249c8763e 100644
> --- a/drivers/net/wireless/ath/ath12k/core.h
> +++ b/drivers/net/wireless/ath/ath12k/core.h
> @@ -588,6 +588,7 @@ struct ath12k_dbg_htt_stats {
>   struct ath12k_debug {
>   	struct dentry *debugfs_pdev;
>   	struct dentry *debugfs_pdev_symlink;
> +	struct dentry *debugfs_pdev_symlink_default;
>   	struct ath12k_dbg_htt_stats htt_stats;
>   	enum wmi_halphy_ctrl_path_stats_id tpc_stats_type;
>   	bool tpc_request;
> @@ -673,6 +674,7 @@ struct ath12k {
>   	u8 pdev_idx;
>   	u8 lmac_id;
>   	u8 hw_link_id;
> +	u8 radio_idx;
>   
>   	struct completion peer_assoc_done;
>   	struct completion peer_delete_done;
> diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
> index 358031fa14eb..8c81a1c22449 100644
> --- a/drivers/net/wireless/ath/ath12k/debugfs.c
> +++ b/drivers/net/wireless/ath/ath12k/debugfs.c
> @@ -1473,18 +1473,35 @@ void ath12k_debugfs_register(struct ath12k *ar)
>   {
>   	struct ath12k_base *ab = ar->ab;
>   	struct ieee80211_hw *hw = ar->ah->hw;
> -	char pdev_name[5];
> +	struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
> +	struct dentry *ath12k_fs;
>   	char buf[100] = {};
> +	char pdev_name[5];
>   
>   	scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
>   
>   	ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
>   
>   	/* Create a symlink under ieee80211/phy* */
> -	scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
> -	ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
> -								hw->wiphy->debugfsdir,
> -								buf);
> +	if (ar->radio_idx == 0) {
> +		scnprintf(buf, sizeof(buf), "../../ath12k/%pd2",
> +			  ar->debug.debugfs_pdev);
> +		ath12k_fs = hw->wiphy->debugfsdir;
> +
> +		/* symbolic link for compatibility */
> +		ar->debug.debugfs_pdev_symlink_default = debugfs_create_symlink("ath12k",
> +										ath12k_fs,
> +										buf);
> +	}
> +
> +	if (ah->num_radio > 1) {
> +		scnprintf(buf, sizeof(buf), "../../../ath12k/%pd2",
> +			  ar->debug.debugfs_pdev);
> +		ath12k_fs = hw->wiphy->radio_cfg[ar->radio_idx].radio_debugfsdir;
> +		ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
> +									ath12k_fs,
> +									buf);
> +	}
>   
>   	if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
>   		debugfs_create_file("dfs_simulate_radar", 0200,
> @@ -1513,7 +1530,9 @@ void ath12k_debugfs_unregister(struct ath12k *ar)
>   
>   	/* Remove symlink under ieee80211/phy* */
>   	debugfs_remove(ar->debug.debugfs_pdev_symlink);
> +	debugfs_remove(ar->debug.debugfs_pdev_symlink_default);
>   	debugfs_remove_recursive(ar->debug.debugfs_pdev);
>   	ar->debug.debugfs_pdev_symlink = NULL;
> +	ar->debug.debugfs_pdev_symlink_default = NULL;
>   	ar->debug.debugfs_pdev = NULL;
>   }
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 553ec28b6aaa..c2b747f1b9f5 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -15065,6 +15065,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
>   		ar->hw_link_id = pdev->hw_link_id;
>   		ar->pdev = pdev;
>   		ar->pdev_idx = pdev_idx;
> +		ar->radio_idx = i;
>   		pdev->ar = ar;
>   
>   		ag->hw_links[ar->hw_link_id].device_id = ab->device_id;
> @@ -15132,7 +15133,6 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
>   		if (!ab)
>   			continue;
>   
> -		ath12k_debugfs_pdev_create(ab);
>   		ath12k_mac_set_device_defaults(ab);
>   		total_radio += ab->num_radios;
>   	}
> 
> base-commit: 15551ababf6d4e857f2101366a0c3eaa86dd822c


Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH ath-next v4 2/6] wifi: ath12k: Add ath12k_hw_params for IPQ5424
From: Baochen Qiang @ 2026-04-03  9:01 UTC (permalink / raw)
  To: Raj Kumar Bhagat, Johannes Berg, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jeff Johnson
  Cc: linux-wireless, devicetree, linux-kernel, ath12k,
	Saravanakumar Duraisamy
In-Reply-To: <20260402-ath12k-ipq5424-v4-2-cd1e0f0a6c88@oss.qualcomm.com>



On 4/2/2026 11:54 AM, Raj Kumar Bhagat wrote:
> From: Saravanakumar Duraisamy <quic_saradura@quicinc.com>
> 
> Add ath12k_hw_params for the ath12k AHB-based WiFi 7 device IPQ5424.
> The WiFi device IPQ5424 is similar to IPQ5332. Most of the hardware
> parameters like hw_ops, wmi_init, ring_mask, etc., are the same between
> IPQ5424 and IPQ5332, hence use these same parameters for IPQ5424.
> Some parameters are specific to IPQ5424; initially set these to
> 0 or NULL, and populate them in subsequent patches.
> 
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1
> Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.6-01275-QCAHKSWPL_SILICONZ-1
> Tested-on: IPQ5424 hw1.0 AHB WLAN.WBE.1.6-01275-QCAHKSWPL_SILICONZ-1
> 
> Signed-off-by: Saravanakumar Duraisamy <quic_saradura@quicinc.com>
> Signed-off-by: Raj Kumar Bhagat <raj.bhagat@oss.qualcomm.com>
> ---
>  drivers/net/wireless/ath/ath12k/core.h     |  1 +
>  drivers/net/wireless/ath/ath12k/wifi7/hw.c | 75 ++++++++++++++++++++++++++++++
>  2 files changed, 76 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
> index 59c193b24764..68453594eba8 100644
> --- a/drivers/net/wireless/ath/ath12k/core.h
> +++ b/drivers/net/wireless/ath/ath12k/core.h
> @@ -157,6 +157,7 @@ enum ath12k_hw_rev {
>  	ATH12K_HW_WCN7850_HW20,
>  	ATH12K_HW_IPQ5332_HW10,
>  	ATH12K_HW_QCC2072_HW10,
> +	ATH12K_HW_IPQ5424_HW10,
>  };
>  
>  enum ath12k_firmware_mode {
> diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> index ec6dba96640b..9b9ca06a9f45 100644
> --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> @@ -753,6 +753,81 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
>  
>  		.dp_primary_link_only = false,
>  	},
> +	{
> +		.name = "ipq5424 hw1.0",
> +		.hw_rev = ATH12K_HW_IPQ5424_HW10,
> +		.fw = {
> +			.dir = "IPQ5424/hw1.0",
> +			.board_size = 256 * 1024,
> +			.cal_offset = 128 * 1024,
> +			.m3_loader = ath12k_m3_fw_loader_remoteproc,
> +			.download_aux_ucode = false,
> +		},
> +		.max_radios = 1,
> +		.single_pdev_only = false,
> +		.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,
> +		.internal_sleep_clock = false,
> +
> +		.hw_ops = &qcn9274_ops,
> +		.ring_mask = &ath12k_wifi7_hw_ring_mask_ipq5332,
> +
> +		.host_ce_config = ath12k_wifi7_host_ce_config_ipq5332,
> +		.ce_count = 12,
> +		.target_ce_config = ath12k_wifi7_target_ce_config_wlan_ipq5332,
> +		.target_ce_count = 12,
> +		.svc_to_ce_map =
> +			ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332,
> +		.svc_to_ce_map_len = 18,
> +
> +		.rxdma1_enable = true,
> +		.num_rxdma_per_pdev = 1,
> +		.num_rxdma_dst_ring = 0,
> +		.rx_mac_buf_ring = false,
> +		.vdev_start_delay = false,
> +
> +		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
> +				   BIT(NL80211_IFTYPE_AP) |
> +				   BIT(NL80211_IFTYPE_MESH_POINT),
> +		.supports_monitor = true,
> +
> +		.idle_ps = false,
> +		.download_calib = true,
> +		.supports_suspend = false,
> +		.tcl_ring_retry = true,
> +		.reoq_lut_support = false,
> +		.supports_shadow_regs = false,
> +
> +		.num_tcl_banks = 48,
> +		.max_tx_ring = 4,
> +
> +		.wmi_init = &ath12k_wifi7_wmi_init_qcn9274,
> +
> +		.qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
> +
> +		.rfkill_pin = 0,
> +		.rfkill_cfg = 0,
> +		.rfkill_on_level = 0,
> +
> +		.rddm_size = 0,
> +
> +		.def_num_link = 0,
> +		.max_mlo_peer = 256,
> +
> +		.otp_board_id_register = 0,
> +
> +		.supports_sta_ps = false,
> +
> +		.acpi_guid = NULL,
> +		.supports_dynamic_smps_6ghz = false,
> +		.iova_mask = 0,
> +		.supports_aspm = false,
> +
> +		.ce_ie_addr = NULL,
> +		.ce_remap = NULL,
> +		.bdf_addr_offset = 0x940000,
> +
> +		.dp_primary_link_only = true,
> +	},
>  };

mhi_config and current_cc_support are missing, please explicitly set them.

>  
>  /* Note: called under rcu_read_lock() */
> 


^ permalink raw reply

* Re: [PATCH ath-next v4 0/6] wifi: ath12k: Enable IPQ5424 AHB WiFi device
From: Baochen Qiang @ 2026-04-03  9:13 UTC (permalink / raw)
  To: Raj Kumar Bhagat, Johannes Berg, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jeff Johnson
  Cc: linux-wireless, devicetree, linux-kernel, ath12k,
	Saravanakumar Duraisamy, Sowmiya Sree Elavalagan,
	Krzysztof Kozlowski
In-Reply-To: <20260402-ath12k-ipq5424-v4-0-cd1e0f0a6c88@oss.qualcomm.com>



On 4/2/2026 11:53 AM, Raj Kumar Bhagat wrote:
> Add support for the new ath12k AHB device IPQ5424, as currently, Ath12k
> AHB only supports IPQ5332 WiFi devices.
> 
> The IPQ5424 is an IEEE 802.11be 2 GHz WiFi device, supporting 4x4
> configurations. To enable the IPQ5424 device:
> - Add the necessary hardware parameters for IPQ5424.
> - Modify the boot-up sequence for ath12k AHB to accommodate the
>   requirements of the IPQ5424 device.
> 
> ---
> Changes in v4:
> - DT binding: dropped copyright update as per discussion in v3.
> - DT binding: Used DT binding from v2 and retained Acked-by tag.
> - Link to v3: https://patch.msgid.link/20260331-ath12k-ipq5424-v3-0-1455b9cae29c@oss.qualcomm.com
> 
> Changes in v3:
> - DT binding: updated copyright.
> - DT binding: Dropped Acked-by tag as copyright is updated.
> - Rebased on latest ToT.
> - Dropped ath12k_ahb_ops because qcom_mdt_load() and
>   qcom_mdt_load_no_init() now have different number of arguments.
> - Link to v2: https://lore.kernel.org/all/20250518-ath12k-ipq5424-v2-0-ef81b833dc97@quicinc.com/
> 
> Changes in v2:
> - DT binding: Removed the redundant example for IPQ5424, as it is similar
>   to IPQ5332.
> - Added driver probe data structure to eliminate the redundant switch-case
>   logic in the ath12k_ahb_probe() function.
> - Validation completed, hence changed from RFC to PATCH.
> - Link to v1: https://lore.kernel.org/all/20250130051838.1924079-1-quic_rajkbhag@quicinc.com/
> 
> Signed-off-by: Raj Kumar Bhagat <raj.bhagat@oss.qualcomm.com>
> 
> ---
> Raj Kumar Bhagat (2):
>       dt-bindings: net: wireless: add ath12k wifi device IPQ5424
>       wifi: ath12k: add ath12k_hw_version_map entry for IPQ5424
> 
> Saravanakumar Duraisamy (3):
>       wifi: ath12k: Add ath12k_hw_params for IPQ5424
>       wifi: ath12k: add ath12k_hw_regs for IPQ5424
>       wifi: ath12k: Add CE remap hardware parameters for IPQ5424
> 
> Sowmiya Sree Elavalagan (1):
>       wifi: ath12k: Enable IPQ5424 WiFi device support
> 
>  .../bindings/net/wireless/qcom,ipq5332-wifi.yaml   |  1 +
>  drivers/net/wireless/ath/ath12k/ahb.c              | 36 +++++----
>  drivers/net/wireless/ath/ath12k/ahb.h              |  1 +
>  drivers/net/wireless/ath/ath12k/ce.h               | 13 ++-
>  drivers/net/wireless/ath/ath12k/core.h             |  1 +
>  drivers/net/wireless/ath/ath12k/wifi7/ahb.c        |  8 ++
>  drivers/net/wireless/ath/ath12k/wifi7/hal.c        |  7 ++
>  drivers/net/wireless/ath/ath12k/wifi7/hal.h        |  3 +
>  .../net/wireless/ath/ath12k/wifi7/hal_qcn9274.c    | 88 ++++++++++++++++++++
>  .../net/wireless/ath/ath12k/wifi7/hal_qcn9274.h    |  1 +
>  drivers/net/wireless/ath/ath12k/wifi7/hw.c         | 93 +++++++++++++++++++++-
>  11 files changed, 231 insertions(+), 21 deletions(-)
> ---
> base-commit: 15551ababf6d4e857f2101366a0c3eaa86dd822c
> change-id: 20260331-ath12k-ipq5424-cddb63a46a97
> 

only nit in patch 2/6, so for patches 2-6/6:

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

> 


^ permalink raw reply

* Re: [PATCH v3 11/15] media: qcom: Switch to generic PAS TZ APIs
From: Jorge Ramirez @ 2026-04-03  9:37 UTC (permalink / raw)
  To: Sumit Garg
  Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
	netdev, linux-wireless, ath12k, linux-remoteproc, andersson,
	konradybcio, robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo,
	lumag, abhinav.kumar, jesszhan0024, marijn.suijten, airlied,
	simona, vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
	andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
	mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
	jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
	amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
	harshal.dev, linux-kernel, Sumit Garg
In-Reply-To: <20260327131043.627120-12-sumit.garg@kernel.org>

On 27/03/26 18:40:39, Sumit Garg wrote:
> From: Sumit Garg <sumit.garg@oss.qualcomm.com>
> 
> Switch qcom media client drivers over to generic PAS TZ APIs. Generic PAS
> TZ service allows to support multiple TZ implementation backends like QTEE
> based SCM PAS service, OP-TEE based PAS service and any further future TZ
> backend service.

OP-TEE based PAS service relies on the linux driver to configure the
iommu (just as it is done on the no_tz case). This generic patch does
not cover that requirement.

Because of that, it is probably better if the commit message doesnt
mention OP-TEE and instead maybe indicate that PAS wll support TEEs that
implement the same restrictions that QTEE (ie, iommu configuration).

I can send an RFC for OP-TEE support based on the integration work being
carried out here [1]

[1] https://github.com/OP-TEE/optee_os/pull/7721#discussion_r3016923507

> 
> Along with that pass proper PAS ID to set_remote_state API. As per testing
> the SCM backend just ignores it while OP-TEE makes use of it to for proper
> book keeping purpose.
> 
> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
> ---
>  drivers/media/platform/qcom/iris/Kconfig      | 25 ++++++++++---------
>  .../media/platform/qcom/iris/iris_firmware.c  |  9 ++++---
>  drivers/media/platform/qcom/venus/Kconfig     |  1 +
>  drivers/media/platform/qcom/venus/firmware.c  | 11 ++++----
>  4 files changed, 25 insertions(+), 21 deletions(-)
> 

^ permalink raw reply

* RE: wifi: rtw89: rtw8922ae: HWSI bus lockup during RF recalibration on AP bandwidth change
From: Jeffrey Wälti @ 2026-04-03 10:43 UTC (permalink / raw)
  To: Ping-Ke Shih; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <nPBjkph3lQo2eiuYIDyn7Mx8rg_pYRHNkQ-yyIVecS7isXyz4KC77Kud29sqnGKgCVgZS_IM1Jj28gx1RN4iaLuyKhS_MZVUnXhy-BVGCfQ=@waelti.dev>

Jeffrey Wälti <jeffrey@waelti.dev> wrote:

> Ping-Ke Shih <pkshih@realtek.com> wrote:
> 
> > Jeffrey Wälti <jeffrey@waelti.dev> wrote:
> > >
> > > Ping-Ke Shih <pkshih@realtek.com> wrote:
> > >
> > > > Jeffrey Wälti <jeffrey@waelti.dev> wrote:
> > > > >
> > > > > <pkshih@realtek.com> wrote:
> > > > >
> > > > > >
> > > > > > Please try to disable power save and ASPM by
> > > > > > 1) iw wlan0 set power_save off
> > >
> > > I'm sorry, this is my first time interacting with the mailing list and I overlooked the other instructions.
> > > It seems like disabling power save gets rid of the issue of Wi-Fi timeouts. I haven't been able to
> > > reproduce the issue with `iw wlan0 set power_save off` yet, even without any of the other fixes on kernel
> > > 6.19.10 and 7.0-rc6.
> > >
> > > > > > 2) reference and install
> > > > > https://github.com/lwfinger/rtw89/blob/main/70-rtw89.conf
> > > > > >    and then cold reboot.
> > > >
> > > > Have you tested with these conditions?
> > >
> > > Using this patch eliminates the issue of Bluetooth devices disconnecting, when switching between
> > > networks.
> > >
> > > > [...]
> > > >
> > > > > >
> > > > > > Please help to test the latest kernel 7.0-rc with additional patch [1].
> > > > > >
> > > > > > [1]
> > > > > https://lore.kernel.org/linux-wireless/20260310080146.31113-4-pkshih@realtek
> > > > > .com/
> > > >
> > > > Have you also applied this patch?
> > >
> > > I tested kernel 7.0-rc6 with this patch applied on top for ~1 day now and haven't been able to reproduce,
> > > even with power save enabled. However, it is a bit difficult to reliably trigger the issue as it seems
> > > to trigger more on certain networks than others etc.
> > >
> > > > > >
> > > > > > Ping-Ke
> > > > > >
> > > > > >
> > > > >
> > > > > Thank you for coming back to me so quickly, I just encountered the same thing
> > > > > with kernel 7.0-rc5.
> > > > >
> > > >
> > > > Please confirm my questions above.
> > > >
> > > > Ping-Ke
> > > >
> > > >
> > >
> > > In summary:
> > > - Disabling power save seems to stop the timeouts but Bluetooth issues remain
> > > - Disabling ASPM features fixes the Bluetooth issue
> > > - kernel 7.0-rc6 with the additional patch fixes Wi-Fi timeouts but not the Bluetooth disconnects
> > >
> > > I hope that answers your questions.
> >
> > It looks like additional patch can fix the WiFi timeouts problem, and
> > disabling ASPM feature can fix Bluetooth issue. I think you can keep
> > (2) + (3) setting as workaround.
> >
> > I'd talk with BT coexistence team internally to figure out the cause
> > of Bluetooth disconnection.
> 
> As always, thank you very much for coming back to me so quickly and working on a fix. Please do let me know if there is any progress on the issue or if you need any more help testing a patch.

Hi again,

I'm sorry for coming back to you so quickly once again, but I am sad to report, that I just encountered the same issue again with kernel 7.0-rc6 and the custom patch applied. After resume the Wi-Fi connection ran at less than 1/100 of the expected speed and wouldn't come back up, until I reconnected to the same network. It seems like just the custom patch was not enough to fix the underlying issue, but it did fix the HWSI lock up. This is what dmesg tells me.

[126462.035430] PM: suspend exit
[126465.615935] wlan0: authenticate with 68:67:c7:2a:20:43 (local address=7c:fa:80:c3:5b:f9)
[126465.615944] wlan0: send auth to 68:67:c7:2a:20:43 (try 1/3)
[126465.634818] wlan0: send auth to 68:67:c7:2a:20:43 (try 2/3)
[126465.654072] wlan0: send auth to 68:67:c7:2a:20:43 (try 3/3)
[126465.673115] wlan0: authentication with 68:67:c7:2a:20:43 timed out
[126466.065780] wlan0: authenticate with 68:67:c7:2a:20:42 (local address=7c:fa:80:c3:5b:f9)
[126466.065789] wlan0: send auth to 68:67:c7:2a:20:42 (try 1/3)
[126468.082718] wlan0: send auth to 68:67:c7:2a:20:42 (try 2/3)
[126470.107802] wlan0: send auth to 68:67:c7:2a:20:42 (try 3/3)
[126471.070743] wlan0: aborting authentication with 68:67:c7:2a:20:42 by local choice (Reason: 3=DEAUTH_LEAVING)
[126474.858695] wlan0: authenticate with 68:67:c7:2a:20:43 (local address=7c:fa:80:c3:5b:f9)
[126474.858705] wlan0: send auth to 68:67:c7:2a:20:43 (try 1/3)
[126474.879430] wlan0: authenticate with 68:67:c7:2a:20:43 (local address=7c:fa:80:c3:5b:f9)
[126474.879439] wlan0: send auth to 68:67:c7:2a:20:43 (try 1/3)
[126474.884633] wlan0: authenticated
[126474.885578] wlan0: associate with 68:67:c7:2a:20:43 (try 1/3)
[126474.899521] wlan0: RX AssocResp from 68:67:c7:2a:20:43 (capab=0x1011 status=0 aid=20)
[126475.002744] wlan0: associated
[126475.002799] wlan0: Limiting TX power to 23 (23 - 0) dBm as advertised by 68:67:c7:2a:20:43
[126490.802365] ideapad_acpi VPC2004:00: unexpected charge_types: both [Fast] and [Long_Life] are enabled
[126627.760736] ideapad_acpi VPC2004:00: unexpected charge_types: both [Fast] and [Long_Life] are enabled

(Here I decide to manually reconnect to the same network)

[126737.556015] wlan0: deauthenticating from 68:67:c7:2a:20:43 by local choice (Reason: 3=DEAUTH_LEAVING)
[126738.215678] wlan0: authenticate with 68:67:c7:2a:20:43 (local address=7c:fa:80:c3:5b:f9)
[126738.215697] wlan0: send auth to 68:67:c7:2a:20:43 (try 1/3)
[126740.272244] wlan0: send auth to 68:67:c7:2a:20:43 (try 2/3)
[126740.291264] wlan0: authenticate with 68:67:c7:2a:20:43 (local address=7c:fa:80:c3:5b:f9)
[126740.291271] wlan0: send auth to 68:67:c7:2a:20:43 (try 1/3)
[126740.293310] wlan0: authenticated
[126740.294214] wlan0: associate with 68:67:c7:2a:20:43 (try 1/3)
[126740.303679] wlan0: RX AssocResp from 68:67:c7:2a:20:43 (capab=0x1011 status=0 aid=21)
[126740.409430] wlan0: associated
[126740.409517] wlan0: Limiting TX power to 23 (23 - 0) dBm as advertised by 68:67:c7:2a:20:43

I will resume testing with the power save function turned off, to check if that still is a working workaround for now.

Jeffrey

^ permalink raw reply

* mt7996e kernel panic
From: Matteo Croce @ 2026-04-03 13:35 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee; +Cc: linux-wireless, linux-kernel

Hi,

I'm experiencing a crash with the mt7996e driver.

The system is OpenWrt running on a Banana Pi R4, so kernel is 6.12.74 + 
mt76 backport

This is the crash:


[518291.616307] mt7996e 0000:01:00.0: Message 001a0003 (seq 1) timeout
[518291.622615] ap-mld0: HW problem - can not stop rx aggregation for 
4a:11:96:52:7e:6d tid 0
[518291.686603] pcieport 0000:00:00.0: AER: Multiple Uncorrectable 
(Non-Fatal) error message received from 0000:00:00.0
[518291.686603] pcieport 0001:00:00.0: AER: Multiple Uncorrectable 
(Non-Fatal) error message received from 0001:00:00.0
[518291.686628] pcieport 0000:00:00.0: PCIe Bus Error: 
severity=Uncorrectable (Non-Fatal), type=Transaction Layer, (Requester ID)
[518291.697137] pcieport 0001:00:00.0: PCIe Bus Error: 
severity=Uncorrectable (Non-Fatal), type=Transaction Layer, (Requester ID)
[518291.707639] pcieport 0000:00:00.0:   device [14c3:7988] error 
status/mask=00004000/00400000
[518291.707645] pcieport 0000:00:00.0:    [14] CmpltTO                
(First)
[518291.719022] pcieport 0001:00:00.0:   device [14c3:7988] error 
status/mask=00004000/00400000
[518291.730390] pcieport 0000:00:00.0: AER: broadcast error_detected message
[518291.730395] mt7996e 0000:01:00.0: AER: can't recover (no 
error_detected callback)
[518291.738822] pcieport 0001:00:00.0:    [14] CmpltTO                
(First)
[518291.745754] pcieport 0000:00:00.0: AER: device recovery failed
[518291.754122] pcieport 0001:00:00.0: AER: broadcast error_detected message
[518291.786622] Unable to handle kernel paging request at virtual 
address 7ae91c2bcb8708b6
[518291.788007] mt7996e_hif 0001:01:00.0: AER: can't recover (no 
error_detected callback)
[518291.795992] Mem abort info:
[518291.803956] pcieport 0001:00:00.0: AER: device recovery failed
[518291.806766]   ESR = 0x0000000096000004
[518291.806769]   EC = 0x25: DABT (current EL), IL = 32 bits
[518291.821919]   SET = 0, FnV = 0
[518291.825052]   EA = 0, S1PTW = 0
[518291.828278]   FSC = 0x04: level 0 translation fault
[518291.833233] Data abort info:
[518291.836189]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[518291.841761]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[518291.846895]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[518291.852282] [7ae91c2bcb8708b6] address between user and kernel 
address ranges
[518291.859500] Internal error: Oops: 0000000096000004 [#1] SMP
[518291.865152] Modules linked in: pppoe ppp_async nft_fib_inet 
nf_flow_table_inet pppox ppp_generic nft_reject_ipv6 nft_reject_ipv4 
nft_reject_inet nft_reject nft_redir nft_quota nft_numgen nft_nat 
nft_masq nft_log nft_limit nft_hash nft_flow_offload nft_fib_ipv6 
nft_fib_ipv4 nft_fib nft_ct nft_chain_nat nf_tables nf_nat nf_flow_table 
nf_conntrack mt7996e(O) mt76_connac_lib(O) mt76(O) mac80211(O) 
cfg80211(O) slhc sfp rtc_pcf8563 nfnetlink nf_reject_ipv6 nf_reject_ipv4 
nf_log_syslog nf_defrag_ipv6 nf_defrag_ipv4 mdio_i2c macvlan libcrc32c 
compat(O) at24 crypto_safexcel pwm_fan i2c_mux_pca954x i2c_mux 
sha512_arm64 sha1_ce sha1_generic seqiv md5 geniv des_generic libdes 
authencesn authenc leds_gpio xhci_plat_hcd xhci_pci xhci_mtk_hcd 
xhci_hcd gpio_button_hotplug(O) usbcore usb_common aquantia crc_itu_t
[518291.935834] CPU: 3 UID: 0 PID: 22229 Comm: kworker/u16:0 Tainted: 
G        W  O       6.12.74 #0
[518291.944702] Tainted: [W]=WARN, [O]=OOT_MODULE
[518291.949135] Hardware name: Banana Pi BPI-R4 (2x SFP+) (DT)
[518291.954696] Workqueue: mt76 mt7996_mac_reset_work [mt7996e]
[518291.960367] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS 
BTYPE=--)
[518291.967406] pc : __free_pages+0x14/0x88
[518291.971326] lr : mtk_wed_hwrro_free_buffer+0x5c/0xc0
[518291.976371] sp : ffffffc08cf83b80
[518291.979761] x29: ffffffc08cf83b80 x28: ffffff80c5ce4c30 x27: 
ffffff80c5ce4c18
[518291.986976] x26: 0000000000000001 x25: ffffff80c4e1c080 x24: 
ffffffc081d03000
[518291.994188] x23: ffffff80c266f000 x22: ffffff80c2670000 x21: 
0000000000000001
[518292.001401] x20: 7ae91c2bcb8708b6 x19: ffffff80c266f810 x18: 
ffffff80ff7ae100
[518292.008613] x17: ffffffc07eb8b000 x16: ffffffc080e00000 x15: 
0000000000000001
[518292.015825] x14: 0000000000000000 x13: ffffff80c0129cc0 x12: 
0000000000000006
[518292.023037] x11: 0000000000000000 x10: ffffff80c0129cc0 x9 : 
ffffff80ff7ae180
[518292.030249] x8 : 0000000000000000 x7 : ffffffc080d76400 x6 : 
7ae91c2bcb8708ea
[518292.037461] x5 : ffffffc080dafce8 x4 : 0000000000000020 x3 : 
000000000000003f
[518292.044673] x2 : 0000000000000040 x1 : 0000000000000000 x0 : 
7ae91c2bcb8708b6
[518292.051885] Call trace:
[518292.054408]  __free_pages+0x14/0x88
[518292.057974]  mtk_wed_hwrro_free_buffer+0x5c/0xc0
[518292.062668]  mtk_wed_reset_dma+0x78c/0xafc
[518292.066842]  mt7996_dma_reset+0x1b0/0x444 [mt7996e]
[518292.071807]  mt7996_mac_reset_work+0x324/0x1250 [mt7996e]
[518292.077287]  process_one_work+0x174/0x300
[518292.081376]  worker_thread+0x278/0x430
[518292.085202]  kthread+0xd8/0xdc
[518292.088335]  ret_from_fork+0x10/0x20
[518292.091992] Code: 9100d006 910003fd f90013f5 52800035 (f9400004)
[518292.098160] ---[ end trace 0000000000000000 ]---
[518292.110206] pstore: backend (ramoops) writing error (-28)
[518292.115685] Kernel panic - not syncing: Oops: Fatal exception
[518292.121506] SMP: stopping secondary CPUs
[518292.125508] Kernel Offset: disabled
[518292.129073] CPU features: 0x00,00000002,00000000,4200400b
[518292.134548] Memory Limit: none
[518292.144967] Rebooting in 3 seconds..


I resolved the line numbers and I've got:

    __free_pages (include/asm-generic/bitops/generic-non-atomic.h:128)
    mtk_wed_hwrro_free_buffer (drivers/net/ethernet/mediatek/mtk_wed.c:870)
    mtk_wed_reset_dma (drivers/net/ethernet/mediatek/mtk_wed.c:1887)
    mt7996_dma_reset (mt7996/dma.c:1009) [mt7996e]
    mt7996_mac_restart (mt7996/mac.c:2273) [mt7996e]
    process_one_work (kernel/workqueue.c:3235)
    process_scheduled_works (kernel/workqueue.c:3304)
    kthread (kernel/kthread.c:389)
    ret_from_fork (arch/arm64/kernel/entry.S:863)


It happens randomly between a few hours and a few days. I don't know the 
code so I let an AI analyze the crash, for what it's worth, this is its 
analysis:


The crash is a use-after-free / corrupted pointer during a MAC reset 
work handler. The sequence:

1. mt7996 MCU timeout (Message 001a0003 timeout) triggers a MAC reset 
via mt7996_mac_reset_work
2. The reset path calls mt7996_dma_reset(dev, true) → 
mtk_wed_device_dma_reset() → mtk_wed_reset_dma() → mtk_wed_rx_reset() → 
mtk_wed_hwrro_free_buffer()
3. At mtk_wed.c:870-879, the loop iterates over page_list[] entries and 
calls __free_page(page) on each
4. The page pointer is 0x7ae91c2bcb8708b6 (visible in x20/x0 registers) 
— this is a garbage/poisoned value, not a valid kernel pointer
5. __free_page() → __free_pages() tries to test page flags via 
generic_test_bit() and faults on the bad pointer

The root cause is that dev->hw_rro.pages[] contains corrupted entries. 
This is likely because the PCIe Completion Timeout (CmpltTO) errors on 
both PCIe ports
(0000:00:00.0 and 0001:00:00.0) corrupted DMA memory or the device state 
before the reset handler could clean up properly. The 0x7ae91c2bcb87... 
pattern in x20 and x6
(with 0x...08ea vs 0x...08b6 — differing by 0x34 = a struct offset) 
suggests the page_list memory itself was corrupted by stale DMA writes 
after the PCIe link went
down.


Regards,

-- 

Matteo Croce

per aspera ad upstream


^ permalink raw reply

* [PATCH v2 0/7] Enable Bluetooth and WiFi on Fairphone (Gen. 6)
From: Luca Weiss @ 2026-04-03 13:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k,
	Luca Weiss, Dmitry Baryshkov

Add the required bits to enable Bluetooth and WiFi on the Milos
SoC-based Fairphone (Gen. 6) smartphone.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
Changes in v2:
- Drop applied pd-mapper patch
- Add compatibles for wcn6755 with fallback to wcn6750 (wifi & bt)
- Rebase on linux-next
- Pick up one tag (discard the rest due to addition of wcn6755
  compatibles)
- Link to v1: https://lore.kernel.org/r/20260116-milos-fp6-bt-wifi-v1-0-27b4fbb77e9c@fairphone.com

---
Luca Weiss (7):
      regulator: dt-bindings: qcom,qca6390-pmu: Document WCN6755 PMU
      dt-bindings: bluetooth: qcom,wcn6750-bt: Document WCN6755 Bluetooth
      dt-bindings: net: wireless: ath11k: Document WCN6755 WiFi
      arm64: dts: qcom: milos: Split up uart11 pinctrl
      arm64: dts: qcom: milos: Add WCN6755 WiFi node
      arm64: dts: qcom: milos-fairphone-fp6: Enable Bluetooth
      arm64: dts: qcom: milos-fairphone-fp6: Enable WiFi

 .../bindings/net/bluetooth/qcom,wcn6750-bt.yaml    |  10 +-
 .../bindings/net/wireless/qcom,ath11k.yaml         |  16 +-
 .../bindings/regulator/qcom,qca6390-pmu.yaml       |  16 +-
 arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts   | 191 +++++++++++++++++++++
 arch/arm64/boot/dts/qcom/milos.dtsi                |  74 ++++++--
 5 files changed, 285 insertions(+), 22 deletions(-)
---
base-commit: 83acad05dee54a5cff0c98dd7962e55d4c6b145a
change-id: 20260116-milos-fp6-bt-wifi-22faa7b15e8c

Best regards,
--  
Luca Weiss <luca.weiss@fairphone.com>


^ permalink raw reply

* [PATCH v2 1/7] regulator: dt-bindings: qcom,qca6390-pmu: Document WCN6755 PMU
From: Luca Weiss @ 2026-04-03 13:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k,
	Luca Weiss
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-0-393322b27c5f@fairphone.com>

Document the WCN6755 PMU using a fallback to WCN6750 since the two chips
seem to be completely pin and software compatible. In fact the original
downstream kernel just pretends the WCN6755 is a WCN6750.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 .../devicetree/bindings/regulator/qcom,qca6390-pmu.yaml  | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml b/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
index 47c425c9fff1..105174df7df2 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
@@ -16,11 +16,17 @@ description:
 
 properties:
   compatible:
-    enum:
-      - qcom,qca6390-pmu
-      - qcom,wcn6750-pmu
-      - qcom,wcn6855-pmu
-      - qcom,wcn7850-pmu
+    oneOf:
+      - items:
+          - enum:
+              - qcom,wcn6755-pmu
+          - const: qcom,wcn6750-pmu
+
+      - enum:
+          - qcom,qca6390-pmu
+          - qcom,wcn6750-pmu
+          - qcom,wcn6855-pmu
+          - qcom,wcn7850-pmu
 
   vdd-supply:
     description: VDD supply regulator handle

-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 2/7] dt-bindings: bluetooth: qcom,wcn6750-bt: Document WCN6755 Bluetooth
From: Luca Weiss @ 2026-04-03 13:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k,
	Luca Weiss
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-0-393322b27c5f@fairphone.com>

Document the WCN6755 Bluetooth using a fallback to WCN6750 since the two
chips seem to be completely pin and software compatible. In fact the
original downstream kernel just pretends the WCN6755 is a WCN6750.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 .../devicetree/bindings/net/bluetooth/qcom,wcn6750-bt.yaml     | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/bluetooth/qcom,wcn6750-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/qcom,wcn6750-bt.yaml
index 8606a45ac9b9..79522409d709 100644
--- a/Documentation/devicetree/bindings/net/bluetooth/qcom,wcn6750-bt.yaml
+++ b/Documentation/devicetree/bindings/net/bluetooth/qcom,wcn6750-bt.yaml
@@ -12,8 +12,14 @@ maintainers:
 
 properties:
   compatible:
-    enum:
-      - qcom,wcn6750-bt
+    oneOf:
+      - items:
+          - enum:
+              - qcom,wcn6755-bt
+          - const: qcom,wcn6750-bt
+
+      - enum:
+          - qcom,wcn6750-bt
 
   enable-gpios:
     maxItems: 1

-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 3/7] dt-bindings: net: wireless: ath11k: Document WCN6755 WiFi
From: Luca Weiss @ 2026-04-03 13:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k,
	Luca Weiss
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-0-393322b27c5f@fairphone.com>

Document the WCN6755 WiFi using a fallback to WCN6750 since the two
chips seem to be completely pin and software compatible. In fact the
original downstream kernel just pretends the WCN6755 is a WCN6750.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 .../devicetree/bindings/net/wireless/qcom,ath11k.yaml    | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
index 0cc1dbf2beef..94f8f8551756 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
@@ -16,11 +16,17 @@ description: |
 
 properties:
   compatible:
-    enum:
-      - qcom,ipq8074-wifi
-      - qcom,ipq6018-wifi
-      - qcom,wcn6750-wifi
-      - qcom,ipq5018-wifi
+    oneOf:
+      - items:
+          - enum:
+              - qcom,wcn6755-wifi
+          - const: qcom,wcn6750-wifi
+
+      - enum:
+          - qcom,ipq8074-wifi
+          - qcom,ipq6018-wifi
+          - qcom,wcn6750-wifi
+          - qcom,ipq5018-wifi
 
   reg:
     maxItems: 1

-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 4/7] arm64: dts: qcom: milos: Split up uart11 pinctrl
From: Luca Weiss @ 2026-04-03 13:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k,
	Luca Weiss
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-0-393322b27c5f@fairphone.com>

In order to set the pinctrl for the individual CTS, RTS, TX and RX pins,
split up the pinctrl configuration into 4 nodes so that boards can set
some properties separately.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 arch/arm64/boot/dts/qcom/milos.dtsi | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/milos.dtsi b/arch/arm64/boot/dts/qcom/milos.dtsi
index 4a64a98a434b..71292dfd6e08 100644
--- a/arch/arm64/boot/dts/qcom/milos.dtsi
+++ b/arch/arm64/boot/dts/qcom/milos.dtsi
@@ -2099,19 +2099,27 @@ qup_i2c7_data_clk: qup-i2c7-data-clk-state {
 			};
 
 			qup_uart11_cts_rts: qup-uart11-cts-rts-state {
-				/* CTS, RTS */
-				pins = "gpio48", "gpio49";
-				function = "qup1_se4";
-				drive-strength = <2>;
-				bias-pull-down;
+				qup_uart11_cts: cts-pins {
+					pins = "gpio48";
+					function = "qup1_se4";
+				};
+
+				qup_uart11_rts: rts-pins {
+					pins = "gpio49";
+					function = "qup1_se4";
+				};
 			};
 
 			qup_uart11_default: qup-uart11-default-state {
-				/* TX, RX */
-				pins = "gpio50", "gpio51";
-				function = "qup1_se4";
-				drive-strength = <2>;
-				bias-pull-up;
+				qup_uart11_tx: tx-pins {
+					pins = "gpio50";
+					function = "qup1_se4";
+				};
+
+				qup_uart11_rx: rx-pins {
+					pins = "gpio51";
+					function = "qup1_se4";
+				};
 			};
 
 			sdc2_default: sdc2-default-state {

-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 5/7] arm64: dts: qcom: milos: Add WCN6755 WiFi node
From: Luca Weiss @ 2026-04-03 13:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k,
	Luca Weiss
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-0-393322b27c5f@fairphone.com>

Add a node for the WCN6755 WiFi found with the Milos SoC.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 arch/arm64/boot/dts/qcom/milos.dtsi | 46 +++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/milos.dtsi b/arch/arm64/boot/dts/qcom/milos.dtsi
index 71292dfd6e08..3a3d7f2134e8 100644
--- a/arch/arm64/boot/dts/qcom/milos.dtsi
+++ b/arch/arm64/boot/dts/qcom/milos.dtsi
@@ -2438,6 +2438,52 @@ gic_its: msi-controller@17140000 {
 			};
 		};
 
+		wifi: wifi@17110040 {
+			compatible = "qcom,wcn6755-wifi", "qcom,wcn6750-wifi";
+			reg = <0x0 0x17110040 0x0 0x0>;
+
+			iommus = <&apps_smmu 0x1400 0x1>;
+
+			interrupts = <GIC_SPI 768 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 769 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 770 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 771 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 772 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 773 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 774 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 775 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 776 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 777 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 778 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 779 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 780 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 781 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 782 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 783 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 784 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 785 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 786 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 787 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 788 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 789 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 790 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 791 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 792 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 793 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 794 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 795 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 796 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 797 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 798 IRQ_TYPE_EDGE_RISING 0>,
+				     <GIC_SPI 799 IRQ_TYPE_EDGE_RISING 0>;
+
+			qcom,rproc = <&remoteproc_wpss>;
+			qcom,smem-states = <&smp2p_wlan_out 0>;
+			qcom,smem-state-names = "wlan-smp2p-out";
+
+			status = "disabled";
+		};
+
 		timer@17420000 {
 			compatible = "arm,armv7-timer-mem";
 			reg = <0x0 0x17420000 0x0 0x1000>;

-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 6/7] arm64: dts: qcom: milos-fairphone-fp6: Enable Bluetooth
From: Luca Weiss @ 2026-04-03 13:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k,
	Luca Weiss
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-0-393322b27c5f@fairphone.com>

Add the nodes to describe the WCN6755 chip with its PMU and Bluetooth
parts.

Thanks to Alexander Koskovich for helping with the bringup, adding
'clocks' to the PMU node to make Bluetooth work.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts | 174 +++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
index c1899db46e71..db72418b7195 100644
--- a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
+++ b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
@@ -24,6 +24,7 @@ / {
 
 	aliases {
 		serial0 = &uart5;
+		serial1 = &uart11;
 	};
 
 	gpio-keys {
@@ -225,6 +226,67 @@ trip1 {
 			};
 		};
 	};
+
+	wcn6750-pmu {
+		compatible = "qcom,wcn6755-pmu", "qcom,wcn6750-pmu";
+
+		vddaon-supply = <&vreg_s3b>;
+		vddasd-supply = <&vreg_l7b>;
+		vddpmu-supply = <&vreg_s3b>;
+		vddrfa0p8-supply = <&vreg_s3b>;
+		vddrfa1p2-supply = <&vreg_s2b>;
+		vddrfa1p7-supply = <&vreg_s1b>;
+		vddrfa2p2-supply = <&vreg_s1j>;
+
+		bt-enable-gpios = <&tlmm 53 GPIO_ACTIVE_HIGH>;
+
+		clocks = <&rpmhcc RPMH_RF_CLK1>;
+
+		pinctrl-0 = <&bluetooth_enable_default>;
+		pinctrl-names = "default";
+
+		regulators {
+			vreg_pmu_rfa_cmn: ldo0 {
+				regulator-name = "vreg_pmu_rfa_cmn";
+			};
+
+			vreg_pmu_aon_0p59: ldo1 {
+				regulator-name = "vreg_pmu_aon_0p59";
+			};
+
+			vreg_pmu_wlcx_0p8: ldo2 {
+				regulator-name = "vreg_pmu_wlcx_0p8";
+			};
+
+			vreg_pmu_wlmx_0p85: ldo3 {
+				regulator-name = "vreg_pmu_wlmx_0p85";
+			};
+
+			vreg_pmu_btcmx_0p85: ldo4 {
+				regulator-name = "vreg_pmu_btcmx_0p85";
+			};
+
+			vreg_pmu_rfa_0p8: ldo5 {
+				regulator-name = "vreg_pmu_rfa_0p8";
+			};
+
+			vreg_pmu_rfa_1p2: ldo6 {
+				regulator-name = "vreg_pmu_rfa_1p2";
+			};
+
+			vreg_pmu_rfa_1p7: ldo7 {
+				regulator-name = "vreg_pmu_rfa_1p7";
+			};
+
+			vreg_pmu_pcie_0p9: ldo8 {
+				regulator-name = "vreg_pmu_pcie_0p9";
+			};
+
+			vreg_pmu_pcie_1p8: ldo9 {
+				regulator-name = "vreg_pmu_pcie_1p8";
+			};
+		};
+	};
 };
 
 &apps_rsc {
@@ -752,6 +814,39 @@ &pon_resin {
 	status = "okay";
 };
 
+&qup_uart11_cts {
+	/*
+	 * Configure a bias-bus-hold on CTS to lower power
+	 * usage when Bluetooth is turned off. Bus hold will
+	 * maintain a low power state regardless of whether
+	 * the Bluetooth module drives the pin in either
+	 * direction or leaves the pin fully unpowered.
+	 */
+	bias-bus-hold;
+};
+
+&qup_uart11_rts {
+	/* We'll drive RTS, so no pull */
+	drive-strength = <2>;
+	bias-disable;
+};
+
+&qup_uart11_rx {
+	/*
+	 * Configure a pull-up on RX. This is needed to avoid
+	 * garbage data when the TX pin of the Bluetooth module is
+	 * in tri-state (module powered off or not driving the
+	 * signal yet).
+	 */
+	bias-pull-up;
+};
+
+&qup_uart11_tx {
+	/* We'll drive TX, so no pull */
+	drive-strength = <2>;
+	bias-disable;
+};
+
 &qupv3_id_0 {
 	status = "okay";
 };
@@ -810,6 +905,59 @@ &tlmm {
 			       <13 1>, /* NC */
 			       <63 2>; /* WLAN UART */
 
+	qup_uart11_sleep_cts: qup-uart11-sleep-cts-state {
+		pins = "gpio48";
+		function = "gpio";
+		/*
+		 * Configure a bias-bus-hold on CTS to lower power
+		 * usage when Bluetooth is turned off. Bus hold will
+		 * maintain a low power state regardless of whether
+		 * the Bluetooth module drives the pin in either
+		 * direction or leaves the pin fully unpowered.
+		 */
+		bias-bus-hold;
+	};
+
+	qup_uart11_sleep_rts: qup-uart11-sleep-rts-state {
+		pins = "gpio49";
+		function = "gpio";
+		/*
+		 * Configure pull-down on RTS. As RTS is active low
+		 * signal, pull it low to indicate the BT SoC that it
+		 * can wakeup the system anytime from suspend state by
+		 * pulling RX low (by sending wakeup bytes).
+		 */
+		bias-pull-down;
+	};
+
+	qup_uart11_sleep_tx: qup-uart11-sleep-tx-state {
+		pins = "gpio50";
+		function = "gpio";
+		/*
+		 * Configure pull-up on TX when it isn't actively driven
+		 * to prevent BT SoC from receiving garbage during sleep.
+		 */
+		bias-pull-up;
+	};
+
+	qup_uart11_sleep_rx: qup-uart11-sleep-rx-state {
+		pins = "gpio51";
+		function = "gpio";
+		/*
+		 * Configure a pull-up on RX. This is needed to avoid
+		 * garbage data when the TX pin of the Bluetooth module
+		 * is floating which may cause spurious wakeups.
+		 */
+		bias-pull-up;
+	};
+
+	bluetooth_enable_default: bluetooth-enable-default-state {
+		pins = "gpio53";
+		function = "gpio";
+		output-low;
+		bias-disable;
+	};
+
 	sdc2_card_det_n: sdc2-card-det-state {
 		pins = "gpio65";
 		function = "gpio";
@@ -836,6 +984,32 @@ &uart5 {
 	status = "okay";
 };
 
+&uart11 {
+	/delete-property/ interrupts;
+	interrupts-extended = <&intc GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH 0>,
+			      <&tlmm 51 IRQ_TYPE_EDGE_FALLING>;
+
+	pinctrl-1 =  <&qup_uart11_sleep_cts>,
+		     <&qup_uart11_sleep_rts>,
+		     <&qup_uart11_sleep_tx>,
+		     <&qup_uart11_sleep_rx>;
+	pinctrl-names = "default",
+			"sleep";
+
+	status = "okay";
+
+	bluetooth {
+		compatible = "qcom,wcn6755-bt", "qcom,wcn6750-bt";
+
+		vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
+		vddaon-supply = <&vreg_pmu_aon_0p59>;
+		vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>;
+		vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+		vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
+		vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+	};
+};
+
 &ufs_mem_hc {
 	reset-gpios = <&tlmm 167 GPIO_ACTIVE_LOW>;
 

-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 7/7] arm64: dts: qcom: milos-fairphone-fp6: Enable WiFi
From: Luca Weiss @ 2026-04-03 13:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson
  Cc: ~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k,
	Luca Weiss, Dmitry Baryshkov
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-0-393322b27c5f@fairphone.com>

Configure and enable the WiFi node, and add the required pinctrl to
provide the sleep clock from the PMK8550 (PMK7635) to WCN6755.

Thanks to Alexander Koskovich for helping with the bringup, adding
the missing pinctrl to make the WPSS stop crashing.

Link: https://lore.kernel.org/linux-arm-msm/DBF7OWAWQ94M.FSCP4DPF8ZJY@fairphone.com/
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
index db72418b7195..d8ac495ca7c8 100644
--- a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
+++ b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
@@ -242,7 +242,7 @@ wcn6750-pmu {
 
 		clocks = <&rpmhcc RPMH_RF_CLK1>;
 
-		pinctrl-0 = <&bluetooth_enable_default>;
+		pinctrl-0 = <&bluetooth_enable_default>, <&pmk8550_sleep_clk_default>;
 		pinctrl-names = "default";
 
 		regulators {
@@ -766,6 +766,17 @@ &pmiv0104_eusb2_repeater {
 	qcom,tune-usb2-preem = /bits/ 8 <0x6>;
 };
 
+&pmk8550_gpios {
+	pmk8550_sleep_clk_default: sleep-clk-default-state {
+		pins = "gpio5";
+		function = "func1";
+		input-disable;
+		output-enable;
+		bias-disable;
+		power-source = <0>;
+	};
+};
+
 &pmr735b_gpios {
 	s1j_enable_default: s1j-enable-default-state {
 		pins = "gpio1";
@@ -1049,3 +1060,9 @@ &usb_1_hsphy {
 
 	status = "okay";
 };
+
+&wifi {
+	qcom,calibration-variant = "Fairphone_Gen_6";
+
+	status = "okay";
+};

-- 
2.53.0


^ permalink raw reply related

* [PATCH ath-next v6] wifi: ath12k: avoid dynamic alloc when parsing wmi tb
From: Nicolas Escande @ 2026-04-03 14:28 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless

On each WMI message received from the hardware, we alloc a temporary array
of WMI_TAG_MAX entries of type void *. This array is then populated with
pointers of parsed structs depending on the WMI type, and then freed. This
alloc can fail when memory pressure in the system is high enough.

Given the fact that it is scheduled in softirq with the system_bh_wq, we
should not be able to parse more than one WMI message per CPU at any time.

So instead lets move to a per cpu allocated array, that is reused across
calls. This memory is allocated as needed and refcounted to exist only
as long as one struct ath12k_base lives.

ath12k_wmi_tlv_parse_alloc() and ath12k_wmi_tlv_parse() are merged
together as it no longer allocs mem but returns the existing per-cpu one.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00218-QCAHKSWPL_SILICONZ-1

Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
---
changes from v4:
  - moved to a single instance, refcounted per cpu memory alloc
  
changes from v3:
  - simplified ath12k_core_init() with a single statement
  - move perpcu.h include directly to wmi.c

changes from v2:
  - removed now superfluous return in ath12k_wmi_event_teardown_complete()
  - moved ath12k_wmi_tb declaration to wmi.c & added two functions to
    alloc / free it
  - removed useless error message on memory allocation failure

changes from v1:
  - rebased on ath-next 27401c9b1432
  - changed wording according to Jeff's comment
  - moved alloc/cleanup to new module_init/exit functions in the
    ath12k module as per Baochen's comment

changes from RFC:
  - rebased on ath-next 8e0ab5b9adb7
  - converted missing call sites ath12k_wmi_obss_color_collision_event()
    & ath12k_wmi_pdev_temperature_event()
  - changed alloc order & cleanup path in ath12k_core_alloc() as it seems
    it confused people
  - used sizeof(*tb) in ath12k_wmi_tlv_parse()
---
 drivers/net/wireless/ath/ath12k/core.c |   6 +
 drivers/net/wireless/ath/ath12k/wmi.c  | 214 +++++++++----------------
 drivers/net/wireless/ath/ath12k/wmi.h  |   3 +
 3 files changed, 84 insertions(+), 139 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index c31c47fb5a73..6f0f4bfbf699 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -2256,6 +2256,7 @@ void ath12k_core_deinit(struct ath12k_base *ab)
 void ath12k_core_free(struct ath12k_base *ab)
 {
 	timer_delete_sync(&ab->rx_replenish_retry);
+	ath12k_wmi_free();
 	destroy_workqueue(ab->workqueue_aux);
 	destroy_workqueue(ab->workqueue);
 	kfree(ab);
@@ -2280,6 +2281,9 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
 	if (!ab->workqueue_aux)
 		goto err_free_wq;
 
+	if (ath12k_wmi_alloc() < 0)
+		goto err_free_wq_aux;
+
 	mutex_init(&ab->core_lock);
 	spin_lock_init(&ab->base_lock);
 	init_completion(&ab->reset_complete);
@@ -2314,6 +2318,8 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
 
 	return ab;
 
+err_free_wq_aux:
+	destroy_workqueue(ab->workqueue_aux);
 err_free_wq:
 	destroy_workqueue(ab->workqueue);
 err_sc_free:
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 65a05a9520ff..2641a76e9543 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -15,6 +15,8 @@
 #include <linux/time.h>
 #include <linux/of.h>
 #include <linux/cleanup.h>
+#include <linux/percpu.h>
+#include <linux/refcount.h>
 #include "core.h"
 #include "debugfs.h"
 #include "debug.h"
@@ -134,6 +136,10 @@ struct wmi_pdev_set_obss_bitmap_arg {
 	const char *label;
 };
 
+static DEFINE_MUTEX(ath12k_wmi_mutex);
+static refcount_t ath12k_wmi_refcount = REFCOUNT_INIT(0);
+static void __percpu *ath12k_wmi_tb = NULL;
+
 static const struct ath12k_wmi_tlv_policy ath12k_wmi_tlv_policies[] = {
 	[WMI_TAG_ARRAY_BYTE] = { .min_len = 0 },
 	[WMI_TAG_ARRAY_UINT32] = { .min_len = 0 },
@@ -289,29 +295,19 @@ static int ath12k_wmi_tlv_iter_parse(struct ath12k_base *ab, u16 tag, u16 len,
 	return 0;
 }
 
-static int ath12k_wmi_tlv_parse(struct ath12k_base *ar, const void **tb,
-				const void *ptr, size_t len)
-{
-	return ath12k_wmi_tlv_iter(ar, ptr, len, ath12k_wmi_tlv_iter_parse,
-				   (void *)tb);
-}
-
 static const void **
-ath12k_wmi_tlv_parse_alloc(struct ath12k_base *ab,
-			   struct sk_buff *skb, gfp_t gfp)
+ath12k_wmi_tlv_parse(struct ath12k_base *ab, struct sk_buff *skb)
 {
 	const void **tb;
 	int ret;
 
-	tb = kzalloc_objs(*tb, WMI_TAG_MAX, gfp);
-	if (!tb)
-		return ERR_PTR(-ENOMEM);
+	tb = this_cpu_ptr(ath12k_wmi_tb);
+	memset(tb, 0, WMI_TAG_MAX * sizeof(*tb));
 
-	ret = ath12k_wmi_tlv_parse(ab, tb, skb->data, skb->len);
-	if (ret) {
-		kfree(tb);
+	ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
+				  ath12k_wmi_tlv_iter_parse, (void *)tb);
+	if (ret)
 		return ERR_PTR(ret);
-	}
 
 	return tb;
 }
@@ -3911,9 +3907,10 @@ ath12k_wmi_obss_color_collision_event(struct ath12k_base *ab, struct sk_buff *sk
 	const struct wmi_obss_color_collision_event *ev;
 	struct ath12k_link_vif *arvif;
 	u32 vdev_id, evt_type;
+	const void **tb;
 	u64 bitmap;
 
-	const void **tb __free(kfree) = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ath12k_warn(ab, "failed to parse OBSS color collision tlv %ld\n",
 			    PTR_ERR(tb));
@@ -5714,7 +5711,7 @@ static int ath12k_pull_vdev_start_resp_tlv(struct ath12k_base *ab, struct sk_buf
 	const struct wmi_vdev_start_resp_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -5724,13 +5721,11 @@ static int ath12k_pull_vdev_start_resp_tlv(struct ath12k_base *ab, struct sk_buf
 	ev = tb[WMI_TAG_VDEV_START_RESPONSE_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch vdev start resp ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
 	*vdev_rsp = *ev;
 
-	kfree(tb);
 	return 0;
 }
 
@@ -5809,7 +5804,7 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 
 	ath12k_dbg(ab, ATH12K_DBG_WMI, "processing regulatory ext channel list\n");
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -5819,7 +5814,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch reg chan list ext update ev\n");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -5849,7 +5843,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 	if (num_2g_reg_rules > MAX_REG_RULES || num_5g_reg_rules > MAX_REG_RULES) {
 		ath12k_warn(ab, "Num reg rules for 2G/5G exceeds max limit (num_2g_reg_rules: %d num_5g_reg_rules: %d max_rules: %d)\n",
 			    num_2g_reg_rules, num_5g_reg_rules, MAX_REG_RULES);
-		kfree(tb);
 		return -EINVAL;
 	}
 
@@ -5859,7 +5852,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 		if (num_6g_reg_rules_ap[i] > MAX_6GHZ_REG_RULES) {
 			ath12k_warn(ab, "Num 6G reg rules for AP mode(%d) exceeds max limit (num_6g_reg_rules_ap: %d, max_rules: %d)\n",
 				    i, num_6g_reg_rules_ap[i], MAX_6GHZ_REG_RULES);
-			kfree(tb);
 			return -EINVAL;
 		}
 
@@ -5884,14 +5876,12 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 		    num_6g_reg_rules_cl[WMI_REG_VLP_AP][i] >  MAX_6GHZ_REG_RULES) {
 			ath12k_warn(ab, "Num 6g client reg rules exceeds max limit, for client(type: %d)\n",
 				    i);
-			kfree(tb);
 			return -EINVAL;
 		}
 	}
 
 	if (!total_reg_rules) {
 		ath12k_warn(ab, "No reg rules available\n");
-		kfree(tb);
 		return -EINVAL;
 	}
 
@@ -5993,7 +5983,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 						      ext_wmi_reg_rule);
 
 		if (!reg_info->reg_rules_2g_ptr) {
-			kfree(tb);
 			ath12k_warn(ab, "Unable to Allocate memory for 2g rules\n");
 			return -ENOMEM;
 		}
@@ -6027,7 +6016,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 						      ext_wmi_reg_rule);
 
 		if (!reg_info->reg_rules_5g_ptr) {
-			kfree(tb);
 			ath12k_warn(ab, "Unable to Allocate memory for 5g rules\n");
 			return -ENOMEM;
 		}
@@ -6046,7 +6034,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 						      ext_wmi_reg_rule);
 
 		if (!reg_info->reg_rules_6g_ap_ptr[i]) {
-			kfree(tb);
 			ath12k_warn(ab, "Unable to Allocate memory for 6g ap rules\n");
 			return -ENOMEM;
 		}
@@ -6061,7 +6048,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 							      ext_wmi_reg_rule);
 
 			if (!reg_info->reg_rules_6g_client_ptr[j][i]) {
-				kfree(tb);
 				ath12k_warn(ab, "Unable to Allocate memory for 6g client rules\n");
 				return -ENOMEM;
 			}
@@ -6096,7 +6082,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 
 	ath12k_dbg(ab, ATH12K_DBG_WMI, "processed regulatory ext channel list\n");
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6107,7 +6092,7 @@ static int ath12k_pull_peer_del_resp_ev(struct ath12k_base *ab, struct sk_buff *
 	const struct wmi_peer_delete_resp_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6117,7 +6102,6 @@ static int ath12k_pull_peer_del_resp_ev(struct ath12k_base *ab, struct sk_buff *
 	ev = tb[WMI_TAG_PEER_DELETE_RESP_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch peer delete resp ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -6127,7 +6111,6 @@ static int ath12k_pull_peer_del_resp_ev(struct ath12k_base *ab, struct sk_buff *
 	ether_addr_copy(peer_del_resp->peer_macaddr.addr,
 			ev->peer_macaddr.addr);
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6139,7 +6122,7 @@ static int ath12k_pull_vdev_del_resp_ev(struct ath12k_base *ab,
 	const struct wmi_vdev_delete_resp_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6149,13 +6132,11 @@ static int ath12k_pull_vdev_del_resp_ev(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_VDEV_DELETE_RESP_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch vdev delete resp ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
 	*vdev_id = le32_to_cpu(ev->vdev_id);
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6167,7 +6148,7 @@ static int ath12k_pull_bcn_tx_status_ev(struct ath12k_base *ab,
 	const struct wmi_bcn_tx_status_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6177,14 +6158,12 @@ static int ath12k_pull_bcn_tx_status_ev(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_OFFLOAD_BCN_TX_STATUS_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch bcn tx status ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
 	*vdev_id = le32_to_cpu(ev->vdev_id);
 	*tx_status = le32_to_cpu(ev->tx_status);
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6195,7 +6174,7 @@ static int ath12k_pull_vdev_stopped_param_tlv(struct ath12k_base *ab, struct sk_
 	const struct wmi_vdev_stopped_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6205,13 +6184,11 @@ static int ath12k_pull_vdev_stopped_param_tlv(struct ath12k_base *ab, struct sk_
 	ev = tb[WMI_TAG_VDEV_STOPPED_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch vdev stop ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
 	*vdev_id = le32_to_cpu(ev->vdev_id);
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6350,7 +6327,7 @@ static int ath12k_pull_mgmt_tx_compl_param_tlv(struct ath12k_base *ab,
 	const struct wmi_mgmt_tx_compl_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6360,7 +6337,6 @@ static int ath12k_pull_mgmt_tx_compl_param_tlv(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_MGMT_TX_COMPL_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch mgmt tx compl ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -6370,7 +6346,6 @@ static int ath12k_pull_mgmt_tx_compl_param_tlv(struct ath12k_base *ab,
 	param->ppdu_id = ev->ppdu_id;
 	param->ack_rssi = ev->ack_rssi;
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6533,7 +6508,7 @@ static int ath12k_pull_scan_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	const struct wmi_scan_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6543,7 +6518,6 @@ static int ath12k_pull_scan_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	ev = tb[WMI_TAG_SCAN_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch scan ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -6555,7 +6529,6 @@ static int ath12k_pull_scan_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	scan_evt_param->vdev_id = ev->vdev_id;
 	scan_evt_param->tsf_timestamp = ev->tsf_timestamp;
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6566,7 +6539,7 @@ static int ath12k_pull_peer_sta_kickout_ev(struct ath12k_base *ab, struct sk_buf
 	const struct wmi_peer_sta_kickout_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6576,7 +6549,6 @@ static int ath12k_pull_peer_sta_kickout_ev(struct ath12k_base *ab, struct sk_buf
 	ev = tb[WMI_TAG_PEER_STA_KICKOUT_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch peer sta kickout ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -6584,7 +6556,6 @@ static int ath12k_pull_peer_sta_kickout_ev(struct ath12k_base *ab, struct sk_buf
 	arg->reason = le32_to_cpu(ev->reason);
 	arg->rssi = le32_to_cpu(ev->rssi);
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6595,7 +6566,7 @@ static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	const struct wmi_roam_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6605,7 +6576,6 @@ static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	ev = tb[WMI_TAG_ROAM_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch roam ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -6613,7 +6583,6 @@ static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	roam_ev->reason = ev->reason;
 	roam_ev->rssi = ev->rssi;
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6647,7 +6616,7 @@ static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	const struct wmi_chan_info_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6657,7 +6626,6 @@ static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	ev = tb[WMI_TAG_CHAN_INFO_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch chan info ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -6674,7 +6642,6 @@ static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	ch_info_ev->mac_clk_mhz = ev->mac_clk_mhz;
 	ch_info_ev->vdev_id = ev->vdev_id;
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6686,7 +6653,7 @@ ath12k_pull_pdev_bss_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	const struct wmi_pdev_bss_chan_info_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6696,7 +6663,6 @@ ath12k_pull_pdev_bss_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	ev = tb[WMI_TAG_PDEV_BSS_CHAN_INFO_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch pdev bss chan info ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -6714,7 +6680,6 @@ ath12k_pull_pdev_bss_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
 	bss_ch_info_ev->rx_bss_cycle_count_low = ev->rx_bss_cycle_count_low;
 	bss_ch_info_ev->rx_bss_cycle_count_high = ev->rx_bss_cycle_count_high;
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6726,7 +6691,7 @@ ath12k_pull_vdev_install_key_compl_ev(struct ath12k_base *ab, struct sk_buff *sk
 	const struct wmi_vdev_install_key_compl_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6736,7 +6701,6 @@ ath12k_pull_vdev_install_key_compl_ev(struct ath12k_base *ab, struct sk_buff *sk
 	ev = tb[WMI_TAG_VDEV_INSTALL_KEY_COMPLETE_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch vdev install key compl ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
@@ -6746,7 +6710,6 @@ ath12k_pull_vdev_install_key_compl_ev(struct ath12k_base *ab, struct sk_buff *sk
 	arg->key_flags = le32_to_cpu(ev->key_flags);
 	arg->status = le32_to_cpu(ev->status);
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6757,7 +6720,7 @@ static int ath12k_pull_peer_assoc_conf_ev(struct ath12k_base *ab, struct sk_buff
 	const struct wmi_peer_assoc_conf_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6767,14 +6730,12 @@ static int ath12k_pull_peer_assoc_conf_ev(struct ath12k_base *ab, struct sk_buff
 	ev = tb[WMI_TAG_PEER_ASSOC_CONF_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch peer assoc conf ev");
-		kfree(tb);
 		return -EPROTO;
 	}
 
 	peer_assoc_conf->vdev_id = le32_to_cpu(ev->vdev_id);
 	peer_assoc_conf->macaddr = ev->peer_macaddr.addr;
 
-	kfree(tb);
 	return 0;
 }
 
@@ -6792,7 +6753,7 @@ static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *s
 	const void **tb;
 	int ret, i;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6801,7 +6762,6 @@ static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *s
 
 	ev = tb[WMI_TAG_11D_NEW_COUNTRY_EVENT];
 	if (!ev) {
-		kfree(tb);
 		ath12k_warn(ab, "failed to fetch 11d new cc ev");
 		return -EPROTO;
 	}
@@ -6814,8 +6774,6 @@ static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *s
 		   ab->new_alpha2[0],
 		   ab->new_alpha2[1]);
 
-	kfree(tb);
-
 	for (i = 0; i < ab->num_radios; i++) {
 		pdev = &ab->pdevs[i];
 		ar = pdev->ar;
@@ -8557,7 +8515,7 @@ static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,
 	const struct wmi_pdev_ctl_failsafe_chk_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -8567,7 +8525,6 @@ static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch pdev ctl failsafe check ev");
-		kfree(tb);
 		return;
 	}
 
@@ -8581,8 +8538,6 @@ static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,
 	if (ev->ctl_failsafe_status != 0)
 		ath12k_warn(ab, "pdev ctl failsafe failure status %d",
 			    ev->ctl_failsafe_status);
-
-	kfree(tb);
 }
 
 static void
@@ -8654,7 +8609,7 @@ ath12k_wmi_pdev_csa_switch_count_status_event(struct ath12k_base *ab,
 	const u32 *vdev_ids;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -8666,7 +8621,6 @@ ath12k_wmi_pdev_csa_switch_count_status_event(struct ath12k_base *ab,
 
 	if (!ev || !vdev_ids) {
 		ath12k_warn(ab, "failed to fetch pdev csa switch count ev");
-		kfree(tb);
 		return;
 	}
 
@@ -8676,8 +8630,6 @@ ath12k_wmi_pdev_csa_switch_count_status_event(struct ath12k_base *ab,
 		   ev->num_vdevs);
 
 	ath12k_wmi_process_csa_switch_count_event(ab, ev, vdev_ids);
-
-	kfree(tb);
 }
 
 static void
@@ -8689,7 +8641,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
 	struct ath12k *ar;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -8700,7 +8652,6 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
 
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch pdev dfs radar detected ev");
-		kfree(tb);
 		return;
 	}
 
@@ -8739,8 +8690,6 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
 
 exit:
 	rcu_read_unlock();
-
-	kfree(tb);
 }
 
 static void ath12k_tm_wmi_event_segmented(struct ath12k_base *ab, u32 cmd_id,
@@ -8751,7 +8700,7 @@ static void ath12k_tm_wmi_event_segmented(struct ath12k_base *ab, u32 cmd_id,
 	int ret;
 	u16 length;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
@@ -8762,14 +8711,11 @@ static void ath12k_tm_wmi_event_segmented(struct ath12k_base *ab, u32 cmd_id,
 	ev = tb[WMI_TAG_ARRAY_BYTE];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch ftm msg\n");
-		kfree(tb);
 		return;
 	}
 
 	length = skb->len - TLV_HDR_SIZE;
 	ath12k_tm_process_event(ab, cmd_id, ev, length);
-	kfree(tb);
-	tb = NULL;
 }
 
 static void
@@ -8782,7 +8728,7 @@ ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab,
 	int temp;
 	u32 pdev_id;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ath12k_warn(ab, "failed to parse tlv: %ld\n", PTR_ERR(tb));
 		return;
@@ -8791,15 +8737,12 @@ ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch pdev temp ev\n");
-		kfree(tb);
 		return;
 	}
 
 	temp = a_sle32_to_cpu(ev->temp);
 	pdev_id = le32_to_cpu(ev->pdev_id);
 
-	kfree(tb);
-
 	ath12k_dbg(ab, ATH12K_DBG_WMI,
 		   "pdev temperature ev temp %d pdev_id %u\n",
 		   temp, pdev_id);
@@ -8826,7 +8769,7 @@ static void ath12k_fils_discovery_event(struct ath12k_base *ab,
 	const struct wmi_fils_discovery_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab,
@@ -8838,15 +8781,12 @@ static void ath12k_fils_discovery_event(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_HOST_SWFDA_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch FILS discovery event\n");
-		kfree(tb);
 		return;
 	}
 
 	ath12k_warn(ab,
 		    "FILS discovery frame expected from host for vdev_id: %u, transmission scheduled at %u, next TBTT: %u\n",
 		    ev->vdev_id, ev->fils_tt, ev->tbtt);
-
-	kfree(tb);
 }
 
 static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
@@ -8856,7 +8796,7 @@ static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
 	const struct wmi_probe_resp_tx_status_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab,
@@ -8869,7 +8809,6 @@ static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
 	if (!ev) {
 		ath12k_warn(ab,
 			    "failed to fetch probe response transmission status event");
-		kfree(tb);
 		return;
 	}
 
@@ -8877,8 +8816,6 @@ static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
 		ath12k_warn(ab,
 			    "Probe response transmission failed for vdev_id %u, status %u\n",
 			    ev->vdev_id, ev->tx_status);
-
-	kfree(tb);
 }
 
 static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
@@ -8890,7 +8827,7 @@ static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
 	struct ath12k *ar;
 	int ret, vdev_id;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse P2P NoA TLV: %d\n", ret);
@@ -8900,10 +8837,8 @@ static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_P2P_NOA_EVENT];
 	noa = tb[WMI_TAG_P2P_NOA_INFO];
 
-	if (!ev || !noa) {
-		ret = -EPROTO;
-		goto out;
-	}
+	if (!ev || !noa)
+		return -EPROTO;
 
 	vdev_id = __le32_to_cpu(ev->vdev_id);
 
@@ -8926,8 +8861,6 @@ static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
 
 unlock:
 	rcu_read_unlock();
-out:
-	kfree(tb);
 	return ret;
 }
 
@@ -8938,7 +8871,7 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
 	const void **tb;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -8946,10 +8879,8 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
 	}
 
 	ev = tb[WMI_TAG_RFKILL_EVENT];
-	if (!ev) {
-		kfree(tb);
+	if (!ev)
 		return;
-	}
 
 	ath12k_dbg(ab, ATH12K_DBG_MAC,
 		   "wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
@@ -8962,7 +8893,6 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
 	spin_unlock_bh(&ab->base_lock);
 
 	queue_work(ab->workqueue, &ab->rfkill_work);
-	kfree(tb);
 }
 
 static void
@@ -8978,7 +8908,7 @@ static void ath12k_wmi_twt_enable_event(struct ath12k_base *ab,
 	const struct wmi_twt_enable_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse wmi twt enable status event tlv: %d\n",
@@ -8989,15 +8919,12 @@ static void ath12k_wmi_twt_enable_event(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_TWT_ENABLE_COMPLETE_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch twt enable wmi event\n");
-		goto exit;
+		return;
 	}
 
 	ath12k_dbg(ab, ATH12K_DBG_MAC, "wmi twt enable event pdev id %u status %u\n",
 		   le32_to_cpu(ev->pdev_id),
 		   le32_to_cpu(ev->status));
-
-exit:
-	kfree(tb);
 }
 
 static void ath12k_wmi_twt_disable_event(struct ath12k_base *ab,
@@ -9007,7 +8934,7 @@ static void ath12k_wmi_twt_disable_event(struct ath12k_base *ab,
 	const struct wmi_twt_disable_event *ev;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse wmi twt disable status event tlv: %d\n",
@@ -9018,15 +8945,12 @@ static void ath12k_wmi_twt_disable_event(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_TWT_DISABLE_COMPLETE_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch twt disable wmi event\n");
-		goto exit;
+		return;
 	}
 
 	ath12k_dbg(ab, ATH12K_DBG_MAC, "wmi twt disable event pdev id %d status %u\n",
 		   le32_to_cpu(ev->pdev_id),
 		   le32_to_cpu(ev->status));
-
-exit:
-	kfree(tb);
 }
 
 static int ath12k_wmi_wow_wakeup_host_parse(struct ath12k_base *ab,
@@ -9099,7 +9023,7 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
 	const void **tb;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -9109,7 +9033,6 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_GTK_OFFLOAD_STATUS_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch gtk offload status ev");
-		kfree(tb);
 		return;
 	}
 
@@ -9119,7 +9042,6 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
 		rcu_read_unlock();
 		ath12k_warn(ab, "failed to get arvif for vdev_id:%d\n",
 			    le32_to_cpu(ev->vdev_id));
-		kfree(tb);
 		return;
 	}
 
@@ -9135,8 +9057,6 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
 				   (void *)&replay_ctr_be, GFP_ATOMIC);
 
 	rcu_read_unlock();
-
-	kfree(tb);
 }
 
 static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab,
@@ -9148,7 +9068,7 @@ static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab,
 	const void **tb;
 	int ret, i;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse mlo setup complete event tlv: %d\n",
@@ -9159,7 +9079,6 @@ static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab,
 	ev = tb[WMI_TAG_MLO_SETUP_COMPLETE_EVENT];
 	if (!ev) {
 		ath12k_warn(ab, "failed to fetch mlo setup complete event\n");
-		kfree(tb);
 		return;
 	}
 
@@ -9178,14 +9097,11 @@ static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab,
 	if (!ar) {
 		ath12k_warn(ab, "invalid pdev_id %d status %u in setup complete event\n",
 			    ev->pdev_id, ev->status);
-		goto out;
+		return;
 	}
 
 	ar->mlo_setup_status = le32_to_cpu(ev->status);
 	complete(&ar->mlo_setup_done);
-
-out:
-	kfree(tb);
 }
 
 static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab,
@@ -9195,7 +9111,7 @@ static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab,
 	const void **tb;
 	int ret;
 
-	tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+	tb = ath12k_wmi_tlv_parse(ab, skb);
 	if (IS_ERR(tb)) {
 		ret = PTR_ERR(tb);
 		ath12k_warn(ab, "failed to parse teardown complete event tlv: %d\n", ret);
@@ -9203,13 +9119,8 @@ static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab,
 	}
 
 	ev = tb[WMI_TAG_MLO_TEARDOWN_COMPLETE];
-	if (!ev) {
+	if (!ev)
 		ath12k_warn(ab, "failed to fetch teardown complete event\n");
-		kfree(tb);
-		return;
-	}
-
-	kfree(tb);
 }
 
 #ifdef CONFIG_ATH12K_DEBUGFS
@@ -11239,3 +11150,28 @@ int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
 	dev_kfree_skb(skb);
 	return ret;
 }
+
+int ath12k_wmi_alloc(void)
+{
+	guard(mutex)(&ath12k_wmi_mutex);
+
+	if (!ath12k_wmi_tb) {
+		ath12k_wmi_tb = __alloc_percpu(WMI_TAG_MAX * sizeof(void *),
+					       __alignof__(void *));
+		if (!ath12k_wmi_tb)
+			return -ENOMEM;
+	}
+
+	refcount_inc(&ath12k_wmi_refcount);
+	return 0;
+}
+
+void ath12k_wmi_free(void)
+{
+	guard(mutex)(&ath12k_wmi_mutex);
+
+	if (refcount_dec_and_test(&ath12k_wmi_refcount)) {
+		free_percpu(ath12k_wmi_tb);
+		ath12k_wmi_tb = NULL;
+	}
+}
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 5ba9b7d3a888..4a34b2ca99ea 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -6576,4 +6576,7 @@ int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar,
 				       struct ath12k_reg_tpc_power_info *param);
 int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,
 					    struct wmi_mlo_link_set_active_arg *param);
+int ath12k_wmi_alloc(void);
+void ath12k_wmi_free(void);
+
 #endif
-- 
2.53.0


^ permalink raw reply related

* [PATCH] rtlwifi: rtl8821ae: Remove dead code in rtl8821ae_update_hal_rate_table()
From: Chelsy Ratnawat @ 2026-04-03 16:54 UTC (permalink / raw)
  To: pkshih; +Cc: johannes.berg, bhelgaas, linux-wireless, Chelsy Ratnawat

The variable 'mimo_ps' is initialized to IEEE80211_SMPS_OFF and never
modified throughout the function. This makes the condition checking for
IEEE80211_SMPS_STATIC always evaluate to false, rendering the entire
if-branch unreachable dead code.

The error was reported by Coverity Scan.

Signed-off-by: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
---
 .../wireless/realtek/rtlwifi/rtl8821ae/hw.c   | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index 3a4a33476205..81d36041a79b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -3257,7 +3257,6 @@ static void rtl8821ae_update_hal_rate_table(struct ieee80211_hw *hw,
 	u32 ratr_value;
 	u8 ratr_index = 0;
 	u8 b_nmode = mac->ht_enable;
-	u8 mimo_ps = IEEE80211_SMPS_OFF;
 	u16 shortgi_rate;
 	u32 tmp_ratr_value;
 	u8 curtxbw_40mhz = mac->bw_40;
@@ -3288,19 +3287,15 @@ static void rtl8821ae_update_hal_rate_table(struct ieee80211_hw *hw,
 	case WIRELESS_MODE_N_24G:
 	case WIRELESS_MODE_N_5G:
 		b_nmode = 1;
-		if (mimo_ps == IEEE80211_SMPS_STATIC) {
-			ratr_value &= 0x0007F005;
-		} else {
-			u32 ratr_mask;
+		u32 ratr_mask;
 
-			if (get_rf_type(rtlphy) == RF_1T2R ||
-			    get_rf_type(rtlphy) == RF_1T1R)
-				ratr_mask = 0x000ff005;
-			else
-				ratr_mask = 0x0f0ff005;
+		if (get_rf_type(rtlphy) == RF_1T2R ||
+		    get_rf_type(rtlphy) == RF_1T1R)
+			ratr_mask = 0x000ff005;
+		else
+			ratr_mask = 0x0f0ff005;
 
-			ratr_value &= ratr_mask;
-		}
+		ratr_value &= ratr_mask;
 		break;
 	default:
 		if (rtlphy->rf_type == RF_1T2R)
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v2 4/7] arm64: dts: qcom: milos: Split up uart11 pinctrl
From: Dmitry Baryshkov @ 2026-04-03 19:32 UTC (permalink / raw)
  To: Luca Weiss
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
	~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-4-393322b27c5f@fairphone.com>

On Fri, Apr 03, 2026 at 03:52:50PM +0200, Luca Weiss wrote:
> In order to set the pinctrl for the individual CTS, RTS, TX and RX pins,
> split up the pinctrl configuration into 4 nodes so that boards can set
> some properties separately.
> 
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
>  arch/arm64/boot/dts/qcom/milos.dtsi | 28 ++++++++++++++++++----------
>  1 file changed, 18 insertions(+), 10 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH v2 5/7] arm64: dts: qcom: milos: Add WCN6755 WiFi node
From: Dmitry Baryshkov @ 2026-04-03 19:33 UTC (permalink / raw)
  To: Luca Weiss
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Alexander Koskovich, Liam Girdwood, Mark Brown,
	Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Balakrishna Godavarthi, Rocky Liao, Johannes Berg, Jeff Johnson,
	~postmarketos/upstreaming, phone-devel, linux-arm-msm,
	linux-kernel, devicetree, linux-bluetooth, linux-wireless, ath11k
In-Reply-To: <20260403-milos-fp6-bt-wifi-v2-5-393322b27c5f@fairphone.com>

On Fri, Apr 03, 2026 at 03:52:51PM +0200, Luca Weiss wrote:
> Add a node for the WCN6755 WiFi found with the Milos SoC.
> 
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
>  arch/arm64/boot/dts/qcom/milos.dtsi | 46 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 46 insertions(+)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

^ permalink raw reply

* [PATCH] wifi: brcmsmac: phy_lcn: Remove dead code in wlc_lcnphy_radio_2064_channel_tune_4313()
From: Chelsy Ratnawat @ 2026-04-03 19:33 UTC (permalink / raw)
  To: arend.vanspriel
  Cc: linux-wireless, brcm80211, brcm80211-dev-list.pdl,
	Chelsy Ratnawat

The variable rfpll_doubler is initialized to 0 and then unconditionally
set to 1 on the very next line, making the subsequent check for
!rfpll_doubler always evaluate to false. This results in logically
dead code that has never been executed.

Remove the unused variable, the unreachable conditional branch, and
simplify the fpfd calculation to directly use the PLL doubler values.

Signed-off-by: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
---
 .../broadcom/brcm80211/brcmsmac/phy/phy_lcn.c       | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
index 8cec5ad79fda..d65a68045ca8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -1607,7 +1607,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
 {
 	uint i;
 	const struct chan_info_2064_lcnphy *ci;
-	u8 rfpll_doubler = 0;
 	u8 pll_pwrup, pll_pwrup_ovr;
 	s32 qFcal;
 	u8 d15, d16, f16, e44, e45;
@@ -1618,18 +1617,12 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
 	u16 g30, d28;
 
 	ci = &chan_info_2064_lcnphy[0];
-	rfpll_doubler = 1;
 
 	mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
 
 	write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
-	if (!rfpll_doubler) {
-		loop_bw = PLL_2064_LOOP_BW;
-		d30 = PLL_2064_D30;
-	} else {
-		loop_bw = PLL_2064_LOOP_BW_DOUBLER;
-		d30 = PLL_2064_D30_DOUBLER;
-	}
+	loop_bw = PLL_2064_LOOP_BW_DOUBLER;
+	d30 = PLL_2064_D30_DOUBLER;
 
 	if (CHSPEC_IS2G(pi->radio_chanspec)) {
 		for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
@@ -1669,7 +1662,7 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
 	e44 = 0;
 	e45 = 0;
 
-	fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
+	fpfd = pi->xtalfreq << 1;
 	if (pi->xtalfreq > 26000000)
 		e44 = 1;
 	if (pi->xtalfreq > 52000000)
-- 
2.43.0


^ 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