[PATCH] wifi: ath12k: Remove broken frequency range filtering

Saikiran B bjsaikiran at gmail.com
Mon Jan 26 00:28:24 PST 2026


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 at 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 at 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 at 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 at 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;
>> >>
>> >>
>> >
>>



More information about the ath12k mailing list