* [PATCH 0/5] wifi: ath12k: Fix 5 GHz Wi-Fi regression on WCN7850
@ 2026-01-23 15:57 Saikiran
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix firmware stats leak on get_txpower error paths Saikiran
` (4 more replies)
0 siblings, 5 replies; 12+ messages in thread
From: Saikiran @ 2026-01-23 15:57 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, kvalo, Saikiran
This series fixes a critical 5 GHz Wi-Fi regression affecting WCN7850
(Snapdragon X Elite laptops) in kernel 6.17+. On affected systems,
only 2.4 GHz networks are detected while 5 GHz networks are completely
invisible.
The root cause is broken frequency range filtering logic introduced
between kernel 6.16 and 6.17 that filters out all channels when
frequency range values are reset to zero during regulatory updates.
Patch 4/5 is the primary fix that removes the broken filtering logic.
The other patches address related firmware stats handling issues and
regulatory domain initialization problems discovered during debugging.
Tested extensively on WCN7850 hw2.0 with firmware WLAN.HMT.1.1.c5-00302
on Lenovo Yoga Slim 7x (Snapdragon X Elite). Both 2.4 GHz and 5 GHz
networks now work correctly.
Saikiran (5):
wifi: ath12k: Fix firmware stats leak on get_txpower error paths
wifi: ath12k: Initialize regulatory frequency ranges to avoid
filtering all channels
wifi: ath12k: Add fallback regulatory domain for WCN7850 without
SMBIOS
wifi: ath12k: Remove broken frequency range filtering
wifi: ath12k: Fix invalid frequency error in freq_to_idx
drivers/net/wireless/ath/ath12k/core.c | 31 +++++++++++++++++++++
drivers/net/wireless/ath/ath12k/mac.c | 2 ++
drivers/net/wireless/ath/ath12k/reg.c | 13 ---------
drivers/net/wireless/ath/ath12k/wmi.c | 6 +---
4 files changed, 33 insertions(+), 19 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] wifi: ath12k: Fix firmware stats leak on get_txpower error paths
2026-01-23 15:57 [PATCH 0/5] wifi: ath12k: Fix 5 GHz Wi-Fi regression on WCN7850 Saikiran
@ 2026-01-23 15:57 ` Saikiran
2026-01-26 5:22 ` Baochen Qiang
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Initialize regulatory frequency ranges to avoid filtering all channels Saikiran
` (3 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Saikiran @ 2026-01-23 15:57 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, kvalo, Saikiran
The commits bd6ec8111e65 and 2977567b244f changed firmware stats handling
to be caller-driven, requiring explicit ath12k_fw_stats_reset() calls
after using ath12k_mac_get_fw_stats().
However, in ath12k_mac_op_get_txpower(), when ath12k_mac_get_fw_stats()
succeeds but the pdev stats list is empty, or when the stats request
fails, the function exits via err_fallback without resetting the stats
buffer.
This causes the stats buffer to accumulate data, eventually leading to
firmware communication failures (error -71/EPROTO) during subsequent
operations, particularly during 5GHz scanning which requires additional
TX power queries.
Symptoms:
- "failed to pull fw stats: -71" errors in dmesg - 5GHz networks not detected despite hardware support
- 2.4GHz networks work normally
Fix this by calling ath12k_fw_stats_reset() on all error paths after
ath12k_mac_get_fw_stats() is called, ensuring the stats buffer is
always freed regardless of the execution path.
Fixes: bd6ec8111e65 ("wifi: ath12k: Make firmware stats reset caller-driven")
Link: https://bugs.launchpad.net/ubuntu-concept/+bug/2138308
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
Signed-off-by: Saikiran <bjsaikiran@gmail.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index f7a2a544bef2..4195364cb6e3 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -5161,6 +5161,7 @@ static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
ret = ath12k_mac_get_fw_stats(ar, ¶ms);
if (ret) {
ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
+ ath12k_fw_stats_reset(ar);
goto err_fallback;
}
@@ -5169,6 +5170,7 @@ static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
struct ath12k_fw_stats_pdev, list);
if (!pdev) {
spin_unlock_bh(&ar->data_lock);
+ ath12k_fw_stats_reset(ar);
goto err_fallback;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH] wifi: ath12k: Initialize regulatory frequency ranges to avoid filtering all channels
2026-01-23 15:57 [PATCH 0/5] wifi: ath12k: Fix 5 GHz Wi-Fi regression on WCN7850 Saikiran
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix firmware stats leak on get_txpower error paths Saikiran
@ 2026-01-23 15:57 ` Saikiran
2026-01-26 5:26 ` Baochen Qiang
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Add fallback regulatory domain for WCN7850 without SMBIOS Saikiran
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Saikiran @ 2026-01-23 15:57 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, kvalo, Saikiran
Commit 657b0c72c4ad ("wifi: ath12k: Fix frequency range in driver")
added reg_freq_2ghz/5ghz/6ghz structures to intersect regulatory
frequency ranges with hardware capabilities. However, these structures
are never initialized for devices with self-managed regulatory (like
WCN7850).
The WCN7850 firmware manages its own regulatory domain and never calls
ath12k_reg_build_regd() which updates these structures. This leaves
them at {0, 0}, causing this logic in mac.c:
freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_5ghz.end_freq);
// freq_high = min(6000MHz, 0) = 0
Result: ALL 5GHz channels are filtered out and 5GHz WiFi is broken.
Fix: Initialize reg_freq_* structures to full frequency ranges in
ath12k_core_alloc(). For devices with proper regulatory domain
updates, these will be overwritten by ath12k_reg_build_regd().
For WCN7850 with self-managed regulatory, these defaults allow
channels to work.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302
Fixes: 657b0c72c4ad ("wifi: ath12k: Fix frequency range in driver")
Signed-off-by: Saikiran <bjsaikiran@gmail.com>
---
drivers/net/wireless/ath/ath12k/core.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 4121dd14bbcc..99c26ba01304 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -2290,6 +2290,19 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
ab->qmi.num_radios = U8_MAX;
ab->single_chip_mlo_support = false;
+ /* Initialize regulatory frequency ranges to full range.
+ * These will be updated by ath12k_reg_build_regd() when
+ * regulatory domain is set. For WCN7850 with self-managed
+ * regulatory, firmware doesn't call reg_build_regd so we
+ * need sane defaults to avoid filtering out all channels.
+ */
+ ab->reg_freq_2ghz.start_freq = 2312000; /* 2.312 GHz */
+ ab->reg_freq_2ghz.end_freq = 2732000; /* 2.732 GHz */
+ ab->reg_freq_5ghz.start_freq = 5150000; /* 5.150 GHz */
+ ab->reg_freq_5ghz.end_freq = 5945000; /* 5.945 GHz */
+ ab->reg_freq_6ghz.start_freq = 5945000; /* 5.945 GHz */
+ ab->reg_freq_6ghz.end_freq = 7125000; /* 7.125 GHz */
+
/* Device index used to identify the devices in a group.
*
* In Intra-device MLO, only one device present in a group,
--
2.51.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH] wifi: ath12k: Add fallback regulatory domain for WCN7850 without SMBIOS
2026-01-23 15:57 [PATCH 0/5] wifi: ath12k: Fix 5 GHz Wi-Fi regression on WCN7850 Saikiran
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix firmware stats leak on get_txpower error paths Saikiran
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Initialize regulatory frequency ranges to avoid filtering all channels Saikiran
@ 2026-01-23 15:57 ` Saikiran
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Remove broken frequency range filtering Saikiran
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix invalid frequency error in freq_to_idx Saikiran
4 siblings, 0 replies; 12+ messages in thread
From: Saikiran @ 2026-01-23 15:57 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, kvalo, Saikiran
When SMBIOS doesn't provide country code data (common on some Lenovo
X Elite laptops), initialize with world domain (00) and skip sending
it to firmware to let firmware use its default regulatory settings.
Without this, new_alpha2 remains uninitialized and firmware receives
invalid country code, causing repeated regulatory update failures.
Note: This workaround doesn't fully resolve the regulatory failures
seen on WCN7850 hw2.0 with firmware WLAN.HMT.1.1.c5-00302. The firmware
still rejects regulatory settings during early initialization, keeping
the device in passive-scan-only mode for 5GHz channels. Further firmware
debugging is needed to resolve the root cause.
Link: https://bugs.launchpad.net/ubuntu-concept/+bug/2138308
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
Signed-off-by: Saikiran <bjsaikiran@gmail.com>
---
drivers/net/wireless/ath/ath12k/core.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index cc352eef1939..4121dd14bbcc 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -800,6 +800,18 @@ int ath12k_core_check_smbios(struct ath12k_base *ab)
ab->qmi.target.bdf_ext[0] = '\0';
dmi_walk(ath12k_core_check_cc_code_bdfext, ab);
+ /* If SMBIOS doesn't provide country code, initialize with world domain (00)
+ * to let firmware use its default regulatory settings
+ */
+ spin_lock_bh(&ab->base_lock);
+ if (ab->new_alpha2[0] == 0 && ab->new_alpha2[1] == 0) {
+ /* Use world domain - let firmware decide */
+ ab->new_alpha2[0] = '0';
+ ab->new_alpha2[1] = '0';
+ ath12k_info(ab, "No SMBIOS country code, using world regulatory domain\n");
+ }
+ spin_unlock_bh(&ab->base_lock);
+
if (ab->qmi.target.bdf_ext[0] == '\0')
return -ENODATA;
@@ -1522,6 +1534,12 @@ static void ath12k_update_11d(struct work_struct *work)
memcpy(&arg.alpha2, &ab->new_alpha2, 2);
spin_unlock_bh(&ab->base_lock);
+ /* Skip setting country code if it's world domain (00) - let firmware use defaults */
+ if (arg.alpha2[0] == '0' && arg.alpha2[1] == '0') {
+ ath12k_dbg(ab, ATH12K_DBG_WMI, "skip sending world domain to firmware\n");
+ return;
+ }
+
ath12k_dbg(ab, ATH12K_DBG_WMI, "update 11d new cc %c%c\n",
arg.alpha2[0], arg.alpha2[1]);
--
2.51.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH] wifi: ath12k: Remove broken frequency range filtering
2026-01-23 15:57 [PATCH 0/5] wifi: ath12k: Fix 5 GHz Wi-Fi regression on WCN7850 Saikiran
` (2 preceding siblings ...)
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Add fallback regulatory domain for WCN7850 without SMBIOS Saikiran
@ 2026-01-23 15:57 ` Saikiran
2026-01-26 5:45 ` Baochen Qiang
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix invalid frequency error in freq_to_idx Saikiran
4 siblings, 1 reply; 12+ messages in thread
From: Saikiran @ 2026-01-23 15:57 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, kvalo, Saikiran
Between kernel 6.16 and 6.17, ath12k added frequency range filtering in
ath12k_reg_update_chan_list() that filters channels based on
ar->freq_range.start_freq and ar->freq_range.end_freq.
However, these values are reset to 0 in ath12k_regd_update(), causing
the filter to skip ALL channels:
if (channel_freq < 0 || channel_freq > 0) // Always true when end_freq=0
continue; // All channels skipped
This results in no channel list sent to firmware, causing 5 GHz Wi-Fi
to stop working.
Fix by removing the broken frequency range filtering. The firmware
itself handles frequency range restrictions based on hardware capabilities.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
Signed-off-by: Saikiran <bjsaikiran@gmail.com>
---
drivers/net/wireless/ath/ath12k/reg.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
index 2dfcef013277..2d9adc74ac6e 100644
--- a/drivers/net/wireless/ath/ath12k/reg.c
+++ b/drivers/net/wireless/ath/ath12k/reg.c
@@ -153,12 +153,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
if (bands[band]->channels[i].flags &
IEEE80211_CHAN_DISABLED)
continue;
- /* Skip Channels that are not in current radio's range */
- if (bands[band]->channels[i].center_freq <
- KHZ_TO_MHZ(ar->freq_range.start_freq) ||
- bands[band]->channels[i].center_freq >
- KHZ_TO_MHZ(ar->freq_range.end_freq))
- continue;
num_channels++;
}
@@ -190,13 +184,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
if (channel->flags & IEEE80211_CHAN_DISABLED)
continue;
- /* Skip Channels that are not in current radio's range */
- if (bands[band]->channels[i].center_freq <
- KHZ_TO_MHZ(ar->freq_range.start_freq) ||
- bands[band]->channels[i].center_freq >
- KHZ_TO_MHZ(ar->freq_range.end_freq))
- continue;
-
/* TODO: Set to true/false based on some condition? */
ch->allow_ht = true;
ch->allow_vht = true;
--
2.51.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH] wifi: ath12k: Fix invalid frequency error in freq_to_idx
2026-01-23 15:57 [PATCH 0/5] wifi: ath12k: Fix 5 GHz Wi-Fi regression on WCN7850 Saikiran
` (3 preceding siblings ...)
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Remove broken frequency range filtering Saikiran
@ 2026-01-23 15:57 ` Saikiran
2026-01-26 3:38 ` Baochen Qiang
4 siblings, 1 reply; 12+ messages in thread
From: Saikiran @ 2026-01-23 15:57 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, kvalo, Saikiran
During suspend/resume, the following error is observed in dmesg:
ath12k_pci 0004:01:00.0: chan info: invalid frequency <freq> (idx 101 out of bounds)
This occurs because freq_to_idx() incorrectly filters channels based on
ar->freq_range.start_freq and ar->freq_range.end_freq. These values can be
temporarily zeroed out (e.g., during regulatory updates or suspend/resume
sequences) while the hardware is still operational or reporting status.
When these values are zero, the filter skips all valid channels, causing
the function to return the total channel count (e.g. 101) instead of the
actual index, triggering the out-of-bounds warning.
Remove the broken frequency range filtering from freq_to_idx(). Channel
mapping should depend only on the hardware band definition, not on the
transient regulatory frequency range. This mirrors the fix recently applied
to ath12k_reg_update_chan_list().
Tested-on: Lenovo Yoga Slim 7x
Signed-off-by: Saikiran <bjsaikiran@gmail.com>
---
drivers/net/wireless/ath/ath12k/wmi.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index be8b2943094f..bef1b324b62c 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -6576,11 +6576,7 @@ static int freq_to_idx(struct ath12k *ar, int freq)
continue;
for (ch = 0; ch < sband->n_channels; ch++, idx++) {
- if (sband->channels[ch].center_freq <
- KHZ_TO_MHZ(ar->freq_range.start_freq) ||
- sband->channels[ch].center_freq >
- KHZ_TO_MHZ(ar->freq_range.end_freq))
- continue;
+
if (sband->channels[ch].center_freq == freq)
goto exit;
--
2.51.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] wifi: ath12k: Fix invalid frequency error in freq_to_idx
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix invalid frequency error in freq_to_idx Saikiran
@ 2026-01-26 3:38 ` Baochen Qiang
0 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-01-26 3:38 UTC (permalink / raw)
To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
On 1/23/2026 11:57 PM, Saikiran wrote:
> During suspend/resume, the following error is observed in dmesg:
> ath12k_pci 0004:01:00.0: chan info: invalid frequency <freq> (idx 101 out of bounds)
>
> This occurs because freq_to_idx() incorrectly filters channels based on
> ar->freq_range.start_freq and ar->freq_range.end_freq. These values can be
> temporarily zeroed out (e.g., during regulatory updates or suspend/resume
> sequences) while the hardware is still operational or reporting status.
>
> When these values are zero, the filter skips all valid channels, causing
> the function to return the total channel count (e.g. 101) instead of the
> actual index, triggering the out-of-bounds warning.
>
> Remove the broken frequency range filtering from freq_to_idx(). Channel
> mapping should depend only on the hardware band definition, not on the
> transient regulatory frequency range. This mirrors the fix recently applied
> to ath12k_reg_update_chan_list().
>
> Tested-on: Lenovo Yoga Slim 7x
>
> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> ---
> drivers/net/wireless/ath/ath12k/wmi.c | 6 +-----
> 1 file changed, 1 insertion(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
> index be8b2943094f..bef1b324b62c 100644
> --- a/drivers/net/wireless/ath/ath12k/wmi.c
> +++ b/drivers/net/wireless/ath/ath12k/wmi.c
> @@ -6576,11 +6576,7 @@ static int freq_to_idx(struct ath12k *ar, int freq)
> continue;
>
> for (ch = 0; ch < sband->n_channels; ch++, idx++) {
> - if (sband->channels[ch].center_freq <
> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> - sband->channels[ch].center_freq >
> - KHZ_TO_MHZ(ar->freq_range.end_freq))
> - continue;
> +
>
> if (sband->channels[ch].center_freq == freq)
> goto exit;
this has been fixed upstream, though for a different issue.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1fed08c5519d2f929457f354d3c06c6a8c33829c
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] wifi: ath12k: Fix firmware stats leak on get_txpower error paths
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix firmware stats leak on get_txpower error paths Saikiran
@ 2026-01-26 5:22 ` Baochen Qiang
0 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-01-26 5:22 UTC (permalink / raw)
To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
On 1/23/2026 11:57 PM, Saikiran wrote:
> The commits bd6ec8111e65 and 2977567b244f changed firmware stats handling
> to be caller-driven, requiring explicit ath12k_fw_stats_reset() calls
> after using ath12k_mac_get_fw_stats().
>
> However, in ath12k_mac_op_get_txpower(), when ath12k_mac_get_fw_stats()
> succeeds but the pdev stats list is empty, or when the stats request
> fails, the function exits via err_fallback without resetting the stats
> buffer.
>
> This causes the stats buffer to accumulate data, eventually leading to
> firmware communication failures (error -71/EPROTO) during subsequent
> operations, particularly during 5GHz scanning which requires additional
> TX power queries.
IMO the description is bit generic - can you please describe it in detail? like the code
running path? At lease in
ath12k_wmi_tlv_fw_stats_data_parse()/ath12k_wmi_tlv_rssi_chain_parse() there are several
places returning such error code, and in which exact place is it returned?
>
> Symptoms:
> - "failed to pull fw stats: -71" errors in dmesg - 5GHz networks not detected despite hardware support
> - 2.4GHz networks work normally
>
> Fix this by calling ath12k_fw_stats_reset() on all error paths after
> ath12k_mac_get_fw_stats() is called, ensuring the stats buffer is
> always freed regardless of the execution path.
>
> Fixes: bd6ec8111e65 ("wifi: ath12k: Make firmware stats reset caller-driven")
> Link: https://bugs.launchpad.net/ubuntu-concept/+bug/2138308
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
>
> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> ---
> drivers/net/wireless/ath/ath12k/mac.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index f7a2a544bef2..4195364cb6e3 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -5161,6 +5161,7 @@ static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
> ret = ath12k_mac_get_fw_stats(ar, ¶ms);
> if (ret) {
> ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
> + ath12k_fw_stats_reset(ar);
> goto err_fallback;
> }
>
> @@ -5169,6 +5170,7 @@ static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
> struct ath12k_fw_stats_pdev, list);
> if (!pdev) {
> spin_unlock_bh(&ar->data_lock);
> + ath12k_fw_stats_reset(ar);
curious how could this help if the pdev stats list is empty?
> goto err_fallback;
> }
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] wifi: ath12k: Initialize regulatory frequency ranges to avoid filtering all channels
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Initialize regulatory frequency ranges to avoid filtering all channels Saikiran
@ 2026-01-26 5:26 ` Baochen Qiang
0 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-01-26 5:26 UTC (permalink / raw)
To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
On 1/23/2026 11:57 PM, Saikiran wrote:
> Commit 657b0c72c4ad ("wifi: ath12k: Fix frequency range in driver")
> added reg_freq_2ghz/5ghz/6ghz structures to intersect regulatory
> frequency ranges with hardware capabilities. However, these structures
> are never initialized for devices with self-managed regulatory (like
> WCN7850).
>
> The WCN7850 firmware manages its own regulatory domain and never calls
> ath12k_reg_build_regd() which updates these structures. This leaves
> them at {0, 0}, causing this logic in mac.c:
No. That function indeed would be called for WCN7850.
>
> freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_5ghz.end_freq);
> // freq_high = min(6000MHz, 0) = 0
>
> Result: ALL 5GHz channels are filtered out and 5GHz WiFi is broken.
>
> Fix: Initialize reg_freq_* structures to full frequency ranges in
> ath12k_core_alloc(). For devices with proper regulatory domain
> updates, these will be overwritten by ath12k_reg_build_regd().
> For WCN7850 with self-managed regulatory, these defaults allow
> channels to work.
>
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302
> Fixes: 657b0c72c4ad ("wifi: ath12k: Fix frequency range in driver")
>
> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> ---
> drivers/net/wireless/ath/ath12k/core.c | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
> index 4121dd14bbcc..99c26ba01304 100644
> --- a/drivers/net/wireless/ath/ath12k/core.c
> +++ b/drivers/net/wireless/ath/ath12k/core.c
> @@ -2290,6 +2290,19 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
> ab->qmi.num_radios = U8_MAX;
> ab->single_chip_mlo_support = false;
>
> + /* Initialize regulatory frequency ranges to full range.
> + * These will be updated by ath12k_reg_build_regd() when
> + * regulatory domain is set. For WCN7850 with self-managed
> + * regulatory, firmware doesn't call reg_build_regd so we
> + * need sane defaults to avoid filtering out all channels.
> + */
> + ab->reg_freq_2ghz.start_freq = 2312000; /* 2.312 GHz */
> + ab->reg_freq_2ghz.end_freq = 2732000; /* 2.732 GHz */
> + ab->reg_freq_5ghz.start_freq = 5150000; /* 5.150 GHz */
> + ab->reg_freq_5ghz.end_freq = 5945000; /* 5.945 GHz */
> + ab->reg_freq_6ghz.start_freq = 5945000; /* 5.945 GHz */
> + ab->reg_freq_6ghz.end_freq = 7125000; /* 7.125 GHz */
> +
> /* Device index used to identify the devices in a group.
> *
> * In Intra-device MLO, only one device present in a group,
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] wifi: ath12k: Remove broken frequency range filtering
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Remove broken frequency range filtering Saikiran
@ 2026-01-26 5:45 ` Baochen Qiang
[not found] ` <CAAFDt1syi0jLvrho4mnvwsv8HtraT78wP8tCLFHRw3oiTq2E5w@mail.gmail.com>
0 siblings, 1 reply; 12+ messages in thread
From: Baochen Qiang @ 2026-01-26 5:45 UTC (permalink / raw)
To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
On 1/23/2026 11:57 PM, Saikiran wrote:
> Between kernel 6.16 and 6.17, ath12k added frequency range filtering in
> ath12k_reg_update_chan_list() that filters channels based on
> ar->freq_range.start_freq and ar->freq_range.end_freq.
>
> However, these values are reset to 0 in ath12k_regd_update(), causing
Yes, it is reset at the first, but it get re-calculated later. See
ath12k_mac_update_freq_range() called in ath12k_regd_update().
> the filter to skip ALL channels:
> if (channel_freq < 0 || channel_freq > 0) // Always true when end_freq=0
> continue; // All channels skipped
>
> This results in no channel list sent to firmware, causing 5 GHz Wi-Fi
> to stop working.
>
> Fix by removing the broken frequency range filtering. The firmware
> itself handles frequency range restrictions based on hardware capabilities.
>
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
>
> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> ---
> drivers/net/wireless/ath/ath12k/reg.c | 13 -------------
> 1 file changed, 13 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
> index 2dfcef013277..2d9adc74ac6e 100644
> --- a/drivers/net/wireless/ath/ath12k/reg.c
> +++ b/drivers/net/wireless/ath/ath12k/reg.c
> @@ -153,12 +153,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
> if (bands[band]->channels[i].flags &
> IEEE80211_CHAN_DISABLED)
> continue;
> - /* Skip Channels that are not in current radio's range */
> - if (bands[band]->channels[i].center_freq <
> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> - bands[band]->channels[i].center_freq >
> - KHZ_TO_MHZ(ar->freq_range.end_freq))
> - continue;
>
> num_channels++;
> }
> @@ -190,13 +184,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
> if (channel->flags & IEEE80211_CHAN_DISABLED)
> continue;
>
> - /* Skip Channels that are not in current radio's range */
> - if (bands[band]->channels[i].center_freq <
> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> - bands[band]->channels[i].center_freq >
> - KHZ_TO_MHZ(ar->freq_range.end_freq))
> - continue;
> -
> /* TODO: Set to true/false based on some condition? */
> ch->allow_ht = true;
> ch->allow_vht = true;
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] wifi: ath12k: Remove broken frequency range filtering
[not found] ` <CAAFDt1syi0jLvrho4mnvwsv8HtraT78wP8tCLFHRw3oiTq2E5w@mail.gmail.com>
@ 2026-01-26 6:51 ` Baochen Qiang
[not found] ` <CAAFDt1v-CBHPTMHQB2B9o3X547agCj77RF9tpp_sgUAPkUaYSw@mail.gmail.com>
0 siblings, 1 reply; 12+ messages in thread
From: Baochen Qiang @ 2026-01-26 6:51 UTC (permalink / raw)
To: Saikiran B; +Cc: ath12k, linux-wireless, kvalo
On 1/26/2026 2:35 PM, Saikiran B wrote:
> Hi Baochen,
>
> Thanks for the review.
>
> regarding ath12k_mac_update_freq_range(): You are correct that this
> function eventually updates the frequency range.
>
> However, on the WCN7850 (Lenovo Yoga Slim 7x), there is a race condition
> during boot/resume. ath12k_reg_update_chan_list() is being executed *before*
> ath12k_regd_update() has finished populating ar->freq_range.
could you please elaborate on the race?
>
> At that specific moment, ar->freq_range.end_freq is still 0. The check: if
> (center_freq > KHZ_TO_MHZ(ar->freq_range.end_freq)) evaluates to true for
> all channels, causing the driver to silently drop every 5GHz channel from
> the scan list.
>
> If I cannot remove this filter entirely, would you accept a V2 that skips
> the filtering if the range is uninitialized?
>
> Example:
>
> /* Skip check if regulatory range hasn't been populated yet */if
> (ar->freq_range.end_freq != 0 &&
> (center_freq < KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> center_freq > KHZ_TO_MHZ(ar->freq_range.end_freq)))
> continue;
>
> Without this change (or something similar), 5GHz is completely unusable on
> this platform.
>
> Thanks & Regards,
> Jaya saikiran
>
> On Mon, Jan 26, 2026 at 11:15 AM Baochen Qiang <
> baochen.qiang@oss.qualcomm.com> wrote:
>
>>
>>
>> On 1/23/2026 11:57 PM, Saikiran wrote:
>>> Between kernel 6.16 and 6.17, ath12k added frequency range filtering in
>>> ath12k_reg_update_chan_list() that filters channels based on
>>> ar->freq_range.start_freq and ar->freq_range.end_freq.
>>>
>>> However, these values are reset to 0 in ath12k_regd_update(), causing
>>
>> Yes, it is reset at the first, but it get re-calculated later. See
>> ath12k_mac_update_freq_range() called in ath12k_regd_update().
>>
>>> the filter to skip ALL channels:
>>> if (channel_freq < 0 || channel_freq > 0) // Always true when
>> end_freq=0
>>> continue; // All channels skipped
>>>
>>> This results in no channel list sent to firmware, causing 5 GHz Wi-Fi
>>> to stop working.
>>>
>>> Fix by removing the broken frequency range filtering. The firmware
>>> itself handles frequency range restrictions based on hardware
>> capabilities.
>>>
>>> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
>>>
>>> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
>>> ---
>>> drivers/net/wireless/ath/ath12k/reg.c | 13 -------------
>>> 1 file changed, 13 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/ath/ath12k/reg.c
>> b/drivers/net/wireless/ath/ath12k/reg.c
>>> index 2dfcef013277..2d9adc74ac6e 100644
>>> --- a/drivers/net/wireless/ath/ath12k/reg.c
>>> +++ b/drivers/net/wireless/ath/ath12k/reg.c
>>> @@ -153,12 +153,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar,
>> bool wait)
>>> if (bands[band]->channels[i].flags &
>>> IEEE80211_CHAN_DISABLED)
>>> continue;
>>> - /* Skip Channels that are not in current radio's
>> range */
>>> - if (bands[band]->channels[i].center_freq <
>>> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
>>> - bands[band]->channels[i].center_freq >
>>> - KHZ_TO_MHZ(ar->freq_range.end_freq))
>>> - continue;
>>>
>>> num_channels++;
>>> }
>>> @@ -190,13 +184,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar,
>> bool wait)
>>> if (channel->flags & IEEE80211_CHAN_DISABLED)
>>> continue;
>>>
>>> - /* Skip Channels that are not in current radio's
>> range */
>>> - if (bands[band]->channels[i].center_freq <
>>> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
>>> - bands[band]->channels[i].center_freq >
>>> - KHZ_TO_MHZ(ar->freq_range.end_freq))
>>> - continue;
>>> -
>>> /* TODO: Set to true/false based on some
>> condition? */
>>> ch->allow_ht = true;
>>> ch->allow_vht = true;
>>
>>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] wifi: ath12k: Remove broken frequency range filtering
[not found] ` <CAAFDt1v-CBHPTMHQB2B9o3X547agCj77RF9tpp_sgUAPkUaYSw@mail.gmail.com>
@ 2026-01-26 8:28 ` Saikiran B
0 siblings, 0 replies; 12+ messages in thread
From: Saikiran B @ 2026-01-26 8:28 UTC (permalink / raw)
To: Baochen Qiang; +Cc: ath12k, linux-wireless, kvalo
Hi,
After further testing, I've found that the issue is simpler than I
initially thought.
The Real Problem:
The frequency range filtering was added in commit acc152f9be20 for
"split-phy devices" (devices with separate 2.4GHz and 5GHz radios).
However, WCN7850 is a single-phy device that handles both bands on one
radio.
When the filter runs on WCN7850, it incorrectly restricts channels
because the freq_range is set for only one band at a time, causing the
other bands to be filtered out entirely.
Testing Results:
I tested two approaches:
1. Adding a conditional check (skip filter if freq_range.end_freq ==
0) - This did NOT fix the issue
2. Removing the filter entirely - This DOES fix the issue, 5GHz works perfectly
Conclusion:
The frequency range filtering is fundamentally incompatible with
single-phy devices like WCN7850. The firmware already handles
frequency restrictions based on hardware capabilities, so this
driver-level filtering is unnecessary and breaks single-phy devices.
I'll send a V2 that removes the filtering entirely, with an updated
commit message explaining it's designed for split-phy devices and
breaks single-phy devices, If that's ok.
Thanks & Regards,
Saikiran
On Mon, Jan 26, 2026 at 12:33 PM Saikiran B <bjsaikiran@gmail.com> wrote:
>
> Hi Baochen,
>
> Sure.
>
> The Scenario:
> The ath12k_reg_update_chan_list() function filters channels based on ar->freq_range. However, this function can be triggered via a regulatory notifier while ar->freq_range is temporarily uninitialized (zeroed).
>
> The Execution Flow:
>
> - Reset: ath12k_regd_update() starts and resets ar->freq_range to 0 (to prepare for recalculation).
>
> - Trigger: ath12k_regd_update() calls regulatory_set_wiphy_regd(), which triggers the regulatory notifier to other subsystems.
>
> - Race: The notifier callback executes ath12k_reg_update_chan_list().
>
> - Failure: ath12k_reg_update_chan_list() sees ar->freq_range.end_freq == 0. The filter check (center_freq > end_freq) becomes true for all channels.
>
> - Result: All 5GHz channels are erroneously filtered out.
>
> - Observation: On the Lenovo Yoga Slim 7x, this hits consistently during boot and resume. The notifier fires before the driver has finished repopulating the frequency range in ath12k_mac_update_freq_range().
>
> - Proposed Fix: Since we cannot control the notifier timing, I proposed modifying the filter to skip the check if the range is invalid in my previous mail.
>
> Thanks & Regards,
> Saikiran
>
> On Mon, Jan 26, 2026 at 12:22 PM Baochen Qiang <baochen.qiang@oss.qualcomm.com> wrote:
>>
>>
>>
>> On 1/26/2026 2:35 PM, Saikiran B wrote:
>> > Hi Baochen,
>> >
>> > Thanks for the review.
>> >
>> > regarding ath12k_mac_update_freq_range(): You are correct that this
>> > function eventually updates the frequency range.
>> >
>> > However, on the WCN7850 (Lenovo Yoga Slim 7x), there is a race condition
>> > during boot/resume. ath12k_reg_update_chan_list() is being executed *before*
>> > ath12k_regd_update() has finished populating ar->freq_range.
>>
>> could you please elaborate on the race?
>>
>> >
>> > At that specific moment, ar->freq_range.end_freq is still 0. The check: if
>> > (center_freq > KHZ_TO_MHZ(ar->freq_range.end_freq)) evaluates to true for
>> > all channels, causing the driver to silently drop every 5GHz channel from
>> > the scan list.
>> >
>> > If I cannot remove this filter entirely, would you accept a V2 that skips
>> > the filtering if the range is uninitialized?
>> >
>> > Example:
>> >
>> > /* Skip check if regulatory range hasn't been populated yet */if
>> > (ar->freq_range.end_freq != 0 &&
>> > (center_freq < KHZ_TO_MHZ(ar->freq_range.start_freq) ||
>> > center_freq > KHZ_TO_MHZ(ar->freq_range.end_freq)))
>> > continue;
>> >
>> > Without this change (or something similar), 5GHz is completely unusable on
>> > this platform.
>> >
>> > Thanks & Regards,
>> > Jaya saikiran
>> >
>> > On Mon, Jan 26, 2026 at 11:15 AM Baochen Qiang <
>> > baochen.qiang@oss.qualcomm.com> wrote:
>> >
>> >>
>> >>
>> >> On 1/23/2026 11:57 PM, Saikiran wrote:
>> >>> Between kernel 6.16 and 6.17, ath12k added frequency range filtering in
>> >>> ath12k_reg_update_chan_list() that filters channels based on
>> >>> ar->freq_range.start_freq and ar->freq_range.end_freq.
>> >>>
>> >>> However, these values are reset to 0 in ath12k_regd_update(), causing
>> >>
>> >> Yes, it is reset at the first, but it get re-calculated later. See
>> >> ath12k_mac_update_freq_range() called in ath12k_regd_update().
>> >>
>> >>> the filter to skip ALL channels:
>> >>> if (channel_freq < 0 || channel_freq > 0) // Always true when
>> >> end_freq=0
>> >>> continue; // All channels skipped
>> >>>
>> >>> This results in no channel list sent to firmware, causing 5 GHz Wi-Fi
>> >>> to stop working.
>> >>>
>> >>> Fix by removing the broken frequency range filtering. The firmware
>> >>> itself handles frequency range restrictions based on hardware
>> >> capabilities.
>> >>>
>> >>> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
>> >>>
>> >>> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
>> >>> ---
>> >>> drivers/net/wireless/ath/ath12k/reg.c | 13 -------------
>> >>> 1 file changed, 13 deletions(-)
>> >>>
>> >>> diff --git a/drivers/net/wireless/ath/ath12k/reg.c
>> >> b/drivers/net/wireless/ath/ath12k/reg.c
>> >>> index 2dfcef013277..2d9adc74ac6e 100644
>> >>> --- a/drivers/net/wireless/ath/ath12k/reg.c
>> >>> +++ b/drivers/net/wireless/ath/ath12k/reg.c
>> >>> @@ -153,12 +153,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar,
>> >> bool wait)
>> >>> if (bands[band]->channels[i].flags &
>> >>> IEEE80211_CHAN_DISABLED)
>> >>> continue;
>> >>> - /* Skip Channels that are not in current radio's
>> >> range */
>> >>> - if (bands[band]->channels[i].center_freq <
>> >>> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
>> >>> - bands[band]->channels[i].center_freq >
>> >>> - KHZ_TO_MHZ(ar->freq_range.end_freq))
>> >>> - continue;
>> >>>
>> >>> num_channels++;
>> >>> }
>> >>> @@ -190,13 +184,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar,
>> >> bool wait)
>> >>> if (channel->flags & IEEE80211_CHAN_DISABLED)
>> >>> continue;
>> >>>
>> >>> - /* Skip Channels that are not in current radio's
>> >> range */
>> >>> - if (bands[band]->channels[i].center_freq <
>> >>> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
>> >>> - bands[band]->channels[i].center_freq >
>> >>> - KHZ_TO_MHZ(ar->freq_range.end_freq))
>> >>> - continue;
>> >>> -
>> >>> /* TODO: Set to true/false based on some
>> >> condition? */
>> >>> ch->allow_ht = true;
>> >>> ch->allow_vht = true;
>> >>
>> >>
>> >
>>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-01-26 8:28 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-23 15:57 [PATCH 0/5] wifi: ath12k: Fix 5 GHz Wi-Fi regression on WCN7850 Saikiran
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix firmware stats leak on get_txpower error paths Saikiran
2026-01-26 5:22 ` Baochen Qiang
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Initialize regulatory frequency ranges to avoid filtering all channels Saikiran
2026-01-26 5:26 ` Baochen Qiang
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Add fallback regulatory domain for WCN7850 without SMBIOS Saikiran
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Remove broken frequency range filtering Saikiran
2026-01-26 5:45 ` Baochen Qiang
[not found] ` <CAAFDt1syi0jLvrho4mnvwsv8HtraT78wP8tCLFHRw3oiTq2E5w@mail.gmail.com>
2026-01-26 6:51 ` Baochen Qiang
[not found] ` <CAAFDt1v-CBHPTMHQB2B9o3X547agCj77RF9tpp_sgUAPkUaYSw@mail.gmail.com>
2026-01-26 8:28 ` Saikiran B
2026-01-23 15:57 ` [PATCH] wifi: ath12k: Fix invalid frequency error in freq_to_idx Saikiran
2026-01-26 3:38 ` Baochen Qiang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox