diff mbox series

[ath-next,v2] wifi: ath12k: combine channel list for split-phy devices in single-wiphy

Message ID 20250506105624.466019-1-rameshkumar.sundaram@oss.qualcomm.com
State New
Headers show
Series [ath-next,v2] wifi: ath12k: combine channel list for split-phy devices in single-wiphy | expand

Commit Message

Rameshkumar Sundaram May 6, 2025, 10:56 a.m. UTC
When two split-phy devices that support overlapping frequency ranges within
the same band are grouped into an ath12k hardware (HW) setup, they share a
common wiphy instance. Consequently, the channel list (wiphy->bands[])
becomes unified across all associated radios (ar).

For reference, the devices are:
2.4 GHz + 5 GHz Low Band
5 GHz High Band + 6 GHz

The first radio probed within the 5 GHz range (say 5 GHz Low Band) updates
its sband reference (&ar->mac.sbands[NL80211_BAND_5GHZ]) within
wiphy->bands[]. However, when the second 5 GHz radio (5 GHz High Band) is
probed, it replaces the existing wiphy->bands[] entry with its own sub-band
reference. As a result, wiphy->bands[] always reflects the channel list
from the most recently probed radio in that band, restricting supported
channels to those within its specific range for upper-layer.

Fix this by updating the wiphy->bands[] to just enable the channels of
current radio when there exist a radio which already has set it.
This will make sure wiphy->bands[] holds reference of first radio which
got probed in 5 GHz band and subsequent radio just updates the channel list
in the same address space.

Since same sband memory space is shared between radios of a band, while
determining the allowed frequency range of radio, its frequency limits
(ar->freq_range.start_freq, end_freq) should be used.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1

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

*v2:
  - Fixed frequency conversion from KHZ to MHZ in freq_to_idx()

---
 drivers/net/wireless/ath/ath12k/mac.c | 93 +++++++++++++++++++++++++--
 drivers/net/wireless/ath/ath12k/reg.c | 13 ++++
 drivers/net/wireless/ath/ath12k/wmi.c |  9 ++-
 3 files changed, 109 insertions(+), 6 deletions(-)


base-commit: 21346cd925c2567d5f56cdb1421c94815ac10221

Comments

Kang Yang May 15, 2025, 6:34 a.m. UTC | #1
On 5/6/2025 6:56 PM, Rameshkumar Sundaram wrote:
> When two split-phy devices that support overlapping frequency ranges within
> the same band are grouped into an ath12k hardware (HW) setup, they share a
> common wiphy instance. Consequently, the channel list (wiphy->bands[])
> becomes unified across all associated radios (ar).
> 
> For reference, the devices are:
> 2.4 GHz + 5 GHz Low Band
> 5 GHz High Band + 6 GHz
> 
> The first radio probed within the 5 GHz range (say 5 GHz Low Band) updates
> its sband reference (&ar->mac.sbands[NL80211_BAND_5GHZ]) within
> wiphy->bands[]. However, when the second 5 GHz radio (5 GHz High Band) is
> probed, it replaces the existing wiphy->bands[] entry with its own sub-band
> reference. As a result, wiphy->bands[] always reflects the channel list
> from the most recently probed radio in that band, restricting supported
> channels to those within its specific range for upper-layer.
> 
> Fix this by updating the wiphy->bands[] to just enable the channels of
> current radio when there exist a radio which already has set it.
> This will make sure wiphy->bands[] holds reference of first radio which
> got probed in 5 GHz band and subsequent radio just updates the channel list
> in the same address space.
> 
> Since same sband memory space is shared between radios of a band, while
> determining the allowed frequency range of radio, its frequency limits
> (ar->freq_range.start_freq, end_freq) should be used.
> 
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1


Offline sync with aditya:

This patch and patch [1][2] will make WCN7850 update regulatory rules 
and trigger scan incorrectly.

They are based on the design that one chip only supports one band.

This design will limit WCN7850 to one band.
During init, WCN7850 will be limited to one band(such as 5G band) due to 
patch[1]. Then will only update 5G regulatory rules and trigger 5G scan.
If manually set country code by "iw reg set XX", WCN7850 will be limited 
to 2G band due to patch[2]. Then similar issue will happen.


If QCN supports multi bands like WCN i think you will have the same problem.

WIN team needs to figure a new design for this issue to support multi 
bands on one chip too.



[1] 
https://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git/commit/?h=pending&id=b7544de8a2984e61b95c58c1c6c1e8ce659b1021
[2] 
https://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git/commit/?h=pending&id=13324cecbb2c390a11f1fbfe87f3a5e62d6e4591



> 
> Signed-off-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
> ---
> 
> *v2:
>    - Fixed frequency conversion from KHZ to MHZ in freq_to_idx()
> 
> ---
>   drivers/net/wireless/ath/ath12k/mac.c | 93 +++++++++++++++++++++++++--
>   drivers/net/wireless/ath/ath12k/reg.c | 13 ++++
>   drivers/net/wireless/ath/ath12k/wmi.c |  9 ++-
>   3 files changed, 109 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 4dae941c9615..23cbf348e836 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -4131,8 +4131,9 @@ ath12k_mac_select_scan_device(struct ieee80211_hw *hw,
>   		band = NL80211_BAND_6GHZ;
>   
>   	for_each_ar(ah, ar, i) {
> -		/* TODO 5 GHz low high split changes */
> -		if (ar->mac.sbands[band].channels)
> +		if (ar->mac.sbands[band].channels &&
> +		    center_freq >= KHZ_TO_MHZ(ar->freq_range.start_freq) &&
> +		    center_freq <= KHZ_TO_MHZ(ar->freq_range.end_freq))


Though WCN7850 won't reach here, but this is also not good for those 
chips who support multi bands.


>   			return ar;
>   	}
>   
> @@ -10925,6 +10926,32 @@ static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band)
>   	return 0;
>   }
>   
> +static int ath12k_mac_update_band(struct ath12k *ar,
> +				  struct ieee80211_supported_band *orig_band,
> +				  struct ieee80211_supported_band *new_band)
> +{
> +	int i;
> +
> +	if (!orig_band || !new_band)
> +		return -EINVAL;
> +
> +	if (orig_band->band != new_band->band)
> +		return -EINVAL;
> +
> +	for (i = 0; i < new_band->n_channels; i++) {
> +		if (new_band->channels[i].flags & IEEE80211_CHAN_DISABLED)
> +			continue;
> +		/* An enabled channel in new_band should not be already enabled
> +		 * in the orig_band
> +		 */
> +		if (WARN_ON(!(orig_band->channels[i].flags &
> +			      IEEE80211_CHAN_DISABLED)))
> +			return -EINVAL;
> +		orig_band->channels[i].flags &= ~IEEE80211_CHAN_DISABLED;
> +	}
> +	return 0;
> +}
> +
>   static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
>   					   u32 supported_bands,
>   					   struct ieee80211_supported_band *bands[])
> @@ -10935,6 +10962,7 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
>   	u32 phy_id, freq_low, freq_high;
>   	struct ath12k_hw *ah = ar->ah;
>   	void *channels;
> +	int ret;
>   
>   	BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) +
>   		      ARRAY_SIZE(ath12k_5ghz_channels) +
> @@ -10956,7 +10984,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
>   		band->channels = channels;
>   		band->n_bitrates = ath12k_g_rates_size;
>   		band->bitrates = ath12k_g_rates;
> -		bands[NL80211_BAND_2GHZ] = band;
>   
>   		if (ab->hw_params->single_pdev_only) {
>   			phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2GHZ_CAP);
> @@ -10973,6 +11000,22 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
>   					  reg_cap->high_2ghz_chan);
>   
>   		ath12k_mac_update_freq_range(ar, freq_low, freq_high);
> +
> +		if (!bands[NL80211_BAND_2GHZ]) {
> +			bands[NL80211_BAND_2GHZ] = band;
> +		} else {
> +			/* Split mac in same band under same wiphy */
> +			ret = ath12k_mac_update_band(ar, bands[NL80211_BAND_2GHZ], band);
> +			if (ret) {
> +				kfree(channels);
> +				band->channels = NULL;
> +				return ret;
> +			}
> +			ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 2 GHz split mac with start freq %d end freq %d",
> +				   ar->pdev->pdev_id,
> +				   KHZ_TO_MHZ(ar->freq_range.start_freq),
> +				   KHZ_TO_MHZ(ar->freq_range.end_freq));
> +		}
>   	}
>   
>   	if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
> @@ -10991,7 +11034,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
>   			band->channels = channels;
>   			band->n_bitrates = ath12k_a_rates_size;
>   			band->bitrates = ath12k_a_rates;
> -			bands[NL80211_BAND_6GHZ] = band;
>   
>   			freq_low = max(reg_cap->low_5ghz_chan,
>   				       ab->reg_freq_6ghz.start_freq);
> @@ -11004,6 +11046,26 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
>   
>   			ath12k_mac_update_freq_range(ar, freq_low, freq_high);
>   			ah->use_6ghz_regd = true;
> +
> +			if (!bands[NL80211_BAND_6GHZ]) {
> +				bands[NL80211_BAND_6GHZ] = band;
> +			} else {
> +				/* Split mac in same band under same wiphy */
> +				ret = ath12k_mac_update_band(ar,
> +							     bands[NL80211_BAND_6GHZ],
> +							     band);
> +				if (ret) {
> +					kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
> +					ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
> +					kfree(channels);
> +					band->channels = NULL;
> +					return ret;
> +				}
> +				ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 6 GHz split mac with start freq %d end freq %d",
> +					   ar->pdev->pdev_id,
> +					   KHZ_TO_MHZ(ar->freq_range.start_freq),
> +					   KHZ_TO_MHZ(ar->freq_range.end_freq));
> +			}
>   		}
>   
>   		if (reg_cap->low_5ghz_chan < ATH12K_MIN_6GHZ_FREQ) {
> @@ -11022,7 +11084,6 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
>   			band->channels = channels;
>   			band->n_bitrates = ath12k_a_rates_size;
>   			band->bitrates = ath12k_a_rates;
> -			bands[NL80211_BAND_5GHZ] = band;
>   
>   			if (ab->hw_params->single_pdev_only) {
>   				phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5GHZ_CAP);
> @@ -11039,6 +11100,28 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
>   						  reg_cap->high_5ghz_chan);
>   
>   			ath12k_mac_update_freq_range(ar, freq_low, freq_high);
> +
> +			if (!bands[NL80211_BAND_5GHZ]) {
> +				bands[NL80211_BAND_5GHZ] = band;
> +			} else {
> +				/* Split mac in same band under same wiphy */
> +				ret = ath12k_mac_update_band(ar,
> +							     bands[NL80211_BAND_5GHZ],
> +							     band);
> +				if (ret) {
> +					kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
> +					ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
> +					kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
> +					ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
> +					kfree(channels);
> +					band->channels = NULL;
> +					return ret;
> +				}
> +				ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 5 GHz split mac with start freq %d end freq %d",
> +					   ar->pdev->pdev_id,
> +					   KHZ_TO_MHZ(ar->freq_range.start_freq),
> +					   KHZ_TO_MHZ(ar->freq_range.end_freq));
> +			}
>   		}
>   	}
>   
> diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
> index 7048834e0d14..5c577188fa74 100644
> --- a/drivers/net/wireless/ath/ath12k/reg.c
> +++ b/drivers/net/wireless/ath/ath12k/reg.c
> @@ -176,6 +176,12 @@ 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;

Here will make WCN7850 only updates one band's channel list.

>   
>   			num_channels++;
>   		}
> @@ -204,6 +210,13 @@ 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;


Here will make WCN7850 only updates one band's channel list.


> +
>   			/* TODO: Set to true/false based on some condition? */
>   			ch->allow_ht = true;
>   			ch->allow_vht = true;
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
> index ea303dca38b5..dfd36491c024 100644
> --- a/drivers/net/wireless/ath/ath12k/wmi.c
> +++ b/drivers/net/wireless/ath/ath12k/wmi.c
> @@ -5887,9 +5887,16 @@ static int freq_to_idx(struct ath12k *ar, int freq)
>   		if (!sband)
>   			continue;
>   
> -		for (ch = 0; ch < sband->n_channels; ch++, idx++)
> +		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;
> +		}
>   	}
>   
>   exit:
> 
> base-commit: 21346cd925c2567d5f56cdb1421c94815ac10221
Rameshkumar Sundaram May 19, 2025, 3:36 a.m. UTC | #2
On 5/15/2025 12:04 PM, Kang Yang wrote:
> 
> 
> On 5/6/2025 6:56 PM, Rameshkumar Sundaram wrote:
>> When two split-phy devices that support overlapping frequency ranges 
>> within
>> the same band are grouped into an ath12k hardware (HW) setup, they 
>> share a
>> common wiphy instance. Consequently, the channel list (wiphy->bands[])
>> becomes unified across all associated radios (ar).
>>
>> For reference, the devices are:
>> 2.4 GHz + 5 GHz Low Band
>> 5 GHz High Band + 6 GHz
>>
>> The first radio probed within the 5 GHz range (say 5 GHz Low Band) 
>> updates
>> its sband reference (&ar->mac.sbands[NL80211_BAND_5GHZ]) within
>> wiphy->bands[]. However, when the second 5 GHz radio (5 GHz High Band) is
>> probed, it replaces the existing wiphy->bands[] entry with its own 
>> sub-band
>> reference. As a result, wiphy->bands[] always reflects the channel list
>> from the most recently probed radio in that band, restricting supported
>> channels to those within its specific range for upper-layer.
>>
>> Fix this by updating the wiphy->bands[] to just enable the channels of
>> current radio when there exist a radio which already has set it.
>> This will make sure wiphy->bands[] holds reference of first radio which
>> got probed in 5 GHz band and subsequent radio just updates the channel 
>> list
>> in the same address space.
>>
>> Since same sband memory space is shared between radios of a band, while
>> determining the allowed frequency range of radio, its frequency limits
>> (ar->freq_range.start_freq, end_freq) should be used.
>>
>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
> 
> 
> Offline sync with aditya:
> 
> This patch and patch [1][2] will make WCN7850 update regulatory rules 
> and trigger scan incorrectly.
> 
> They are based on the design that one chip only supports one band.
> 
> This design will limit WCN7850 to one band.
> During init, WCN7850 will be limited to one band(such as 5G band) due to 
> patch[1]. Then will only update 5G regulatory rules and trigger 5G scan.
> If manually set country code by "iw reg set XX", WCN7850 will be limited 
> to 2G band due to patch[2]. Then similar issue will happen.
> 
> 
> If QCN supports multi bands like WCN i think you will have the same 
> problem.
> 
> WIN team needs to figure a new design for this issue to support multi 
> bands on one chip too.
> 
> 
> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git/commit/? 
> h=pending&id=b7544de8a2984e61b95c58c1c6c1e8ce659b1021
> [2] https://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git/commit/? 
> h=pending&id=13324cecbb2c390a11f1fbfe87f3a5e62d6e4591
> 
> 
> 

Thanks for pointing this out. we're working on a new change which fixes 
the frequency range marking in [1] & [2] for multi-band ar's, Will re 
base this patch on top it once it lands in public.

>>
>> Signed-off-by: Rameshkumar Sundaram 
>> <rameshkumar.sundaram@oss.qualcomm.com>
>> ---
>>
>> *v2:
>>    - Fixed frequency conversion from KHZ to MHZ in freq_to_idx()
>>
>> ---
>>   drivers/net/wireless/ath/ath12k/mac.c | 93 +++++++++++++++++++++++++--
>>   drivers/net/wireless/ath/ath12k/reg.c | 13 ++++
>>   drivers/net/wireless/ath/ath12k/wmi.c |  9 ++-
>>   3 files changed, 109 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/ 
>> wireless/ath/ath12k/mac.c
>> index 4dae941c9615..23cbf348e836 100644
>> --- a/drivers/net/wireless/ath/ath12k/mac.c
>> +++ b/drivers/net/wireless/ath/ath12k/mac.c
>> @@ -4131,8 +4131,9 @@ ath12k_mac_select_scan_device(struct 
>> ieee80211_hw *hw,
>>           band = NL80211_BAND_6GHZ;
>>       for_each_ar(ah, ar, i) {
>> -        /* TODO 5 GHz low high split changes */
>> -        if (ar->mac.sbands[band].channels)
>> +        if (ar->mac.sbands[band].channels &&
>> +            center_freq >= KHZ_TO_MHZ(ar->freq_range.start_freq) &&
>> +            center_freq <= KHZ_TO_MHZ(ar->freq_range.end_freq))
> 
> 
> Though WCN7850 won't reach here, but this is also not good for those 
> chips who support multi bands.
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 4dae941c9615..23cbf348e836 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -4131,8 +4131,9 @@  ath12k_mac_select_scan_device(struct ieee80211_hw *hw,
 		band = NL80211_BAND_6GHZ;
 
 	for_each_ar(ah, ar, i) {
-		/* TODO 5 GHz low high split changes */
-		if (ar->mac.sbands[band].channels)
+		if (ar->mac.sbands[band].channels &&
+		    center_freq >= KHZ_TO_MHZ(ar->freq_range.start_freq) &&
+		    center_freq <= KHZ_TO_MHZ(ar->freq_range.end_freq))
 			return ar;
 	}
 
@@ -10925,6 +10926,32 @@  static u32 ath12k_get_phy_id(struct ath12k *ar, u32 band)
 	return 0;
 }
 
+static int ath12k_mac_update_band(struct ath12k *ar,
+				  struct ieee80211_supported_band *orig_band,
+				  struct ieee80211_supported_band *new_band)
+{
+	int i;
+
+	if (!orig_band || !new_band)
+		return -EINVAL;
+
+	if (orig_band->band != new_band->band)
+		return -EINVAL;
+
+	for (i = 0; i < new_band->n_channels; i++) {
+		if (new_band->channels[i].flags & IEEE80211_CHAN_DISABLED)
+			continue;
+		/* An enabled channel in new_band should not be already enabled
+		 * in the orig_band
+		 */
+		if (WARN_ON(!(orig_band->channels[i].flags &
+			      IEEE80211_CHAN_DISABLED)))
+			return -EINVAL;
+		orig_band->channels[i].flags &= ~IEEE80211_CHAN_DISABLED;
+	}
+	return 0;
+}
+
 static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 					   u32 supported_bands,
 					   struct ieee80211_supported_band *bands[])
@@ -10935,6 +10962,7 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 	u32 phy_id, freq_low, freq_high;
 	struct ath12k_hw *ah = ar->ah;
 	void *channels;
+	int ret;
 
 	BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) +
 		      ARRAY_SIZE(ath12k_5ghz_channels) +
@@ -10956,7 +10984,6 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 		band->channels = channels;
 		band->n_bitrates = ath12k_g_rates_size;
 		band->bitrates = ath12k_g_rates;
-		bands[NL80211_BAND_2GHZ] = band;
 
 		if (ab->hw_params->single_pdev_only) {
 			phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2GHZ_CAP);
@@ -10973,6 +11000,22 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 					  reg_cap->high_2ghz_chan);
 
 		ath12k_mac_update_freq_range(ar, freq_low, freq_high);
+
+		if (!bands[NL80211_BAND_2GHZ]) {
+			bands[NL80211_BAND_2GHZ] = band;
+		} else {
+			/* Split mac in same band under same wiphy */
+			ret = ath12k_mac_update_band(ar, bands[NL80211_BAND_2GHZ], band);
+			if (ret) {
+				kfree(channels);
+				band->channels = NULL;
+				return ret;
+			}
+			ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 2 GHz split mac with start freq %d end freq %d",
+				   ar->pdev->pdev_id,
+				   KHZ_TO_MHZ(ar->freq_range.start_freq),
+				   KHZ_TO_MHZ(ar->freq_range.end_freq));
+		}
 	}
 
 	if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
@@ -10991,7 +11034,6 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 			band->channels = channels;
 			band->n_bitrates = ath12k_a_rates_size;
 			band->bitrates = ath12k_a_rates;
-			bands[NL80211_BAND_6GHZ] = band;
 
 			freq_low = max(reg_cap->low_5ghz_chan,
 				       ab->reg_freq_6ghz.start_freq);
@@ -11004,6 +11046,26 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 
 			ath12k_mac_update_freq_range(ar, freq_low, freq_high);
 			ah->use_6ghz_regd = true;
+
+			if (!bands[NL80211_BAND_6GHZ]) {
+				bands[NL80211_BAND_6GHZ] = band;
+			} else {
+				/* Split mac in same band under same wiphy */
+				ret = ath12k_mac_update_band(ar,
+							     bands[NL80211_BAND_6GHZ],
+							     band);
+				if (ret) {
+					kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
+					ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
+					kfree(channels);
+					band->channels = NULL;
+					return ret;
+				}
+				ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 6 GHz split mac with start freq %d end freq %d",
+					   ar->pdev->pdev_id,
+					   KHZ_TO_MHZ(ar->freq_range.start_freq),
+					   KHZ_TO_MHZ(ar->freq_range.end_freq));
+			}
 		}
 
 		if (reg_cap->low_5ghz_chan < ATH12K_MIN_6GHZ_FREQ) {
@@ -11022,7 +11084,6 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 			band->channels = channels;
 			band->n_bitrates = ath12k_a_rates_size;
 			band->bitrates = ath12k_a_rates;
-			bands[NL80211_BAND_5GHZ] = band;
 
 			if (ab->hw_params->single_pdev_only) {
 				phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5GHZ_CAP);
@@ -11039,6 +11100,28 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 						  reg_cap->high_5ghz_chan);
 
 			ath12k_mac_update_freq_range(ar, freq_low, freq_high);
+
+			if (!bands[NL80211_BAND_5GHZ]) {
+				bands[NL80211_BAND_5GHZ] = band;
+			} else {
+				/* Split mac in same band under same wiphy */
+				ret = ath12k_mac_update_band(ar,
+							     bands[NL80211_BAND_5GHZ],
+							     band);
+				if (ret) {
+					kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
+					ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
+					kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
+					ar->mac.sbands[NL80211_BAND_2GHZ].channels = NULL;
+					kfree(channels);
+					band->channels = NULL;
+					return ret;
+				}
+				ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac pdev %u identified as 5 GHz split mac with start freq %d end freq %d",
+					   ar->pdev->pdev_id,
+					   KHZ_TO_MHZ(ar->freq_range.start_freq),
+					   KHZ_TO_MHZ(ar->freq_range.end_freq));
+			}
 		}
 	}
 
diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
index 7048834e0d14..5c577188fa74 100644
--- a/drivers/net/wireless/ath/ath12k/reg.c
+++ b/drivers/net/wireless/ath/ath12k/reg.c
@@ -176,6 +176,12 @@  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++;
 		}
@@ -204,6 +210,13 @@  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;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index ea303dca38b5..dfd36491c024 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -5887,9 +5887,16 @@  static int freq_to_idx(struct ath12k *ar, int freq)
 		if (!sband)
 			continue;
 
-		for (ch = 0; ch < sband->n_channels; ch++, idx++)
+		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;
+		}
 	}
 
 exit: