diff mbox series

[ath-next,2/3] wifi: ath12k: Fix frequency range in driver

Message ID 20250408042128.720263-3-quic_rajson@quicinc.com
State New
Headers show
Series wifi: ath12k: Properly update frequency range | expand

Commit Message

Rajat Soni April 8, 2025, 4:21 a.m. UTC
From: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>

During the initial WMI exchange, the firmware updates the
hardware-supported start and end frequencies in the
ath12k_wmi_hal_reg_capabilities_ext_arg structure. These frequencies,
being hardware-supported, may not always align with the current
regulatory operating frequencies. When operating as multiple grouped
hardwares under a single wiphy, the driver advertises these values
directly to the upper layer in the per-radio frequency range,
which can be misleading.

Sample output snippet from iw phyX info command -

[..]
Supported wiphy radios:
          * Idx 0:
                  Frequency Range: 2312 MHz - 2732 MHz
		 [..]

          * Idx 1:
                  Frequency Range: 5150 MHz - 5330 MHz
		 [..]
[..]

The frequency range displayed above is incorrect because the driver
directly advertises the hardware-supported values to the upper layer.

The driver is aware of the current operating regulatory rules, and
hence it can use this information to determine the final operating
start and end frequencies.

To resolve this issue, add support to store the start and end
frequencies received during the regulatory update event.
Then, intersect these with the hardware-supported start and
end frequencies, and finally, advertise the intersected values to the
upper layer.

Sample output snippet from iw phyX info command after the fix -

[..]
Supported wiphy radios:
          * Idx 0:
                  Frequency Range: 2402 MHz - 2472 MHz
		 [..]

          * Idx 1:
                  Frequency Range: 5170 MHz - 5330 MHz
		 [..]
[..]

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

Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Co-developed-by: Rajat Soni <quic_rajson@quicinc.com>
Signed-off-by: Rajat Soni <quic_rajson@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/core.h |  9 ++++++
 drivers/net/wireless/ath/ath12k/mac.c  | 39 ++++++++++++++++++--------
 drivers/net/wireless/ath/ath12k/reg.c  | 13 +++++++++
 3 files changed, 49 insertions(+), 12 deletions(-)

Comments

Vasanthakumar Thiagarajan April 16, 2025, 4:04 a.m. UTC | #1
On 4/8/2025 9:51 AM, Rajat Soni wrote:
> From: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
> 
> During the initial WMI exchange, the firmware updates the
> hardware-supported start and end frequencies in the
> ath12k_wmi_hal_reg_capabilities_ext_arg structure. These frequencies,
> being hardware-supported, may not always align with the current
> regulatory operating frequencies. When operating as multiple grouped
> hardwares under a single wiphy, the driver advertises these values
> directly to the upper layer in the per-radio frequency range,
> which can be misleading.
> 
> Sample output snippet from iw phyX info command -
> 
> [..]
> Supported wiphy radios:
>            * Idx 0:
>                    Frequency Range: 2312 MHz - 2732 MHz
> 		 [..]
> 
>            * Idx 1:
>                    Frequency Range: 5150 MHz - 5330 MHz
> 		 [..]
> [..]
> 
> The frequency range displayed above is incorrect because the driver
> directly advertises the hardware-supported values to the upper layer.
> 
> The driver is aware of the current operating regulatory rules, and
> hence it can use this information to determine the final operating
> start and end frequencies.
> 
> To resolve this issue, add support to store the start and end
> frequencies received during the regulatory update event.
> Then, intersect these with the hardware-supported start and
> end frequencies, and finally, advertise the intersected values to the
> upper layer.
> 
> Sample output snippet from iw phyX info command after the fix -
> 
> [..]
> Supported wiphy radios:
>            * Idx 0:
>                    Frequency Range: 2402 MHz - 2472 MHz
> 		 [..]
> 
>            * Idx 1:
>                    Frequency Range: 5170 MHz - 5330 MHz
> 		 [..]
> [..]
> 
> 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
> 
> Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
> Co-developed-by: Rajat Soni <quic_rajson@quicinc.com>
> Signed-off-by: Rajat Soni <quic_rajson@quicinc.com>

Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Vasanthakumar Thiagarajan April 16, 2025, 4:09 a.m. UTC | #2
On 4/8/2025 9:51 AM, Rajat Soni wrote:
> From: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
> 
> During the initial WMI exchange, the firmware updates the
> hardware-supported start and end frequencies in the
> ath12k_wmi_hal_reg_capabilities_ext_arg structure. These frequencies,
> being hardware-supported, may not always align with the current
> regulatory operating frequencies. When operating as multiple grouped
> hardwares under a single wiphy, the driver advertises these values
> directly to the upper layer in the per-radio frequency range,
> which can be misleading.
> 
> Sample output snippet from iw phyX info command -
> 
> [..]
> Supported wiphy radios:
>            * Idx 0:
>                    Frequency Range: 2312 MHz - 2732 MHz
> 		 [..]
> 
>            * Idx 1:
>                    Frequency Range: 5150 MHz - 5330 MHz
> 		 [..]
> [..]
> 
> The frequency range displayed above is incorrect because the driver
> directly advertises the hardware-supported values to the upper layer.
> 
> The driver is aware of the current operating regulatory rules, and
> hence it can use this information to determine the final operating
> start and end frequencies.
> 
> To resolve this issue, add support to store the start and end
> frequencies received during the regulatory update event.
> Then, intersect these with the hardware-supported start and
> end frequencies, and finally, advertise the intersected values to the
> upper layer.
> 
> Sample output snippet from iw phyX info command after the fix -
> 
> [..]
> Supported wiphy radios:
>            * Idx 0:
>                    Frequency Range: 2402 MHz - 2472 MHz
> 		 [..]
> 
>            * Idx 1:
>                    Frequency Range: 5170 MHz - 5330 MHz
> 		 [..]
> [..]
> 
> 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
> 
> Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
> Co-developed-by: Rajat Soni <quic_rajson@quicinc.com>
> Signed-off-by: Rajat Soni <quic_rajson@quicinc.com>
> ---
>   drivers/net/wireless/ath/ath12k/core.h |  9 ++++++
>   drivers/net/wireless/ath/ath12k/mac.c  | 39 ++++++++++++++++++--------
>   drivers/net/wireless/ath/ath12k/reg.c  | 13 +++++++++
>   3 files changed, 49 insertions(+), 12 deletions(-)
> 

You may need to rebase the series

Applying: wifi: ath12k: Add helper function ath12k_mac_update_freq_range()
Applying: wifi: ath12k: Fix frequency range in driver
error: patch failed: drivers/net/wireless/ath/ath12k/core.h:1122
error: drivers/net/wireless/ath/ath12k/core.h: patch does not apply
Patch failed at 0002 wifi: ath12k: Fix frequency range in driver
Jeff Johnson April 16, 2025, 2:42 p.m. UTC | #3
On 4/15/2025 9:09 PM, Vasanthakumar Thiagarajan wrote:
> You may need to rebase the series
> 
> Applying: wifi: ath12k: Add helper function ath12k_mac_update_freq_range()
> Applying: wifi: ath12k: Fix frequency range in driver
> error: patch failed: drivers/net/wireless/ath/ath12k/core.h:1122
> error: drivers/net/wireless/ath/ath12k/core.h: patch does not apply
> Patch failed at 0002 wifi: ath12k: Fix frequency range in driver

It applied to my 'pending' branch with:
b4 am --prep-3way ...
git am -3 ...

/jeff
Vasanthakumar Thiagarajan April 16, 2025, 4:08 p.m. UTC | #4
On 4/16/2025 8:12 PM, Jeff Johnson wrote:
> On 4/15/2025 9:09 PM, Vasanthakumar Thiagarajan wrote:
>> You may need to rebase the series
>>
>> Applying: wifi: ath12k: Add helper function ath12k_mac_update_freq_range()
>> Applying: wifi: ath12k: Fix frequency range in driver
>> error: patch failed: drivers/net/wireless/ath/ath12k/core.h:1122
>> error: drivers/net/wireless/ath/ath12k/core.h: patch does not apply
>> Patch failed at 0002 wifi: ath12k: Fix frequency range in driver
> 
> It applied to my 'pending' branch with:
> b4 am --prep-3way ...
> git am -3 ...
> 

Ok. I was trying them on main branch. I'll use pending branch for such checks. Thanks.
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index e8d2a0c859f6..8099a5f54e83 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -880,6 +880,11 @@  struct ath12k_soc_dp_stats {
 	struct ath12k_soc_dp_tx_err_stats tx_err;
 };
 
+struct ath12k_reg_freq {
+	u32 start_freq;
+	u32 end_freq;
+};
+
 struct ath12k_mlo_memory {
 	struct target_mem_chunk chunk[ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01];
 	int mlo_mem_size;
@@ -1122,6 +1127,10 @@  struct ath12k_base {
 	enum ath12k_firmware_mode fw_mode;
 	struct ath12k_ftm_event_obj ftm_event_obj;
 
+	struct ath12k_reg_freq reg_freq_2ghz;
+	struct ath12k_reg_freq reg_freq_5ghz;
+	struct ath12k_reg_freq reg_freq_6ghz;
+
 	/* must be last */
 	u8 drv_priv[] __aligned(sizeof(void *));
 };
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 449aca719ad3..8c971a58fb6f 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -10859,16 +10859,17 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 {
 	struct ieee80211_supported_band *band;
 	struct ath12k_wmi_hal_reg_capabilities_ext_arg *reg_cap;
+	struct ath12k_base *ab = ar->ab;
+	u32 phy_id, freq_low, freq_high;
 	struct ath12k_hw *ah = ar->ah;
 	void *channels;
-	u32 phy_id;
 
 	BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) +
 		      ARRAY_SIZE(ath12k_5ghz_channels) +
 		      ARRAY_SIZE(ath12k_6ghz_channels)) !=
 		     ATH12K_NUM_CHANS);
 
-	reg_cap = &ar->ab->hal_reg_cap[ar->pdev_idx];
+	reg_cap = &ab->hal_reg_cap[ar->pdev_idx];
 
 	if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
 		channels = kmemdup(ath12k_2ghz_channels,
@@ -10885,16 +10886,21 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 		band->bitrates = ath12k_g_rates;
 		bands[NL80211_BAND_2GHZ] = band;
 
-		if (ar->ab->hw_params->single_pdev_only) {
+		if (ab->hw_params->single_pdev_only) {
 			phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_2GHZ_CAP);
-			reg_cap = &ar->ab->hal_reg_cap[phy_id];
+			reg_cap = &ab->hal_reg_cap[phy_id];
 		}
+
+		freq_low = max(reg_cap->low_2ghz_chan,
+			       ab->reg_freq_2ghz.start_freq);
+		freq_high = min(reg_cap->high_2ghz_chan,
+				ab->reg_freq_2ghz.end_freq);
+
 		ath12k_mac_update_ch_list(ar, band,
 					  reg_cap->low_2ghz_chan,
 					  reg_cap->high_2ghz_chan);
 
-		ath12k_mac_update_freq_range(ar, reg_cap->low_2ghz_chan,
-					     reg_cap->high_2ghz_chan);
+		ath12k_mac_update_freq_range(ar, freq_low, freq_high);
 	}
 
 	if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
@@ -10914,12 +10920,17 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 			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);
+			freq_high = min(reg_cap->high_5ghz_chan,
+					ab->reg_freq_6ghz.end_freq);
+
 			ath12k_mac_update_ch_list(ar, band,
 						  reg_cap->low_5ghz_chan,
 						  reg_cap->high_5ghz_chan);
 
-			ath12k_mac_update_freq_range(ar, reg_cap->low_5ghz_chan,
-						     reg_cap->high_5ghz_chan);
+			ath12k_mac_update_freq_range(ar, freq_low, freq_high);
 			ah->use_6ghz_regd = true;
 		}
 
@@ -10941,17 +10952,21 @@  static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
 			band->bitrates = ath12k_a_rates;
 			bands[NL80211_BAND_5GHZ] = band;
 
-			if (ar->ab->hw_params->single_pdev_only) {
+			if (ab->hw_params->single_pdev_only) {
 				phy_id = ath12k_get_phy_id(ar, WMI_HOST_WLAN_5GHZ_CAP);
-				reg_cap = &ar->ab->hal_reg_cap[phy_id];
+				reg_cap = &ab->hal_reg_cap[phy_id];
 			}
 
+			freq_low = max(reg_cap->low_5ghz_chan,
+				       ab->reg_freq_5ghz.start_freq);
+			freq_high = min(reg_cap->high_5ghz_chan,
+					ab->reg_freq_5ghz.end_freq);
+
 			ath12k_mac_update_ch_list(ar, band,
 						  reg_cap->low_5ghz_chan,
 						  reg_cap->high_5ghz_chan);
 
-			ath12k_mac_update_freq_range(ar, reg_cap->low_5ghz_chan,
-						     reg_cap->high_5ghz_chan);
+			ath12k_mac_update_freq_range(ar, freq_low, freq_high);
 		}
 	}
 
diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
index 893650f76fb2..e1007b878f91 100644
--- a/drivers/net/wireless/ath/ath12k/reg.c
+++ b/drivers/net/wireless/ath/ath12k/reg.c
@@ -651,6 +651,16 @@  ath12k_reg_update_weather_radar_band(struct ath12k_base *ab,
 	*rule_idx = i;
 }
 
+static void ath12k_reg_update_freq_range(struct ath12k_reg_freq *reg_freq,
+					 struct ath12k_reg_rule *reg_rule)
+{
+	if (reg_freq->start_freq > reg_rule->start_freq)
+		reg_freq->start_freq = reg_rule->start_freq;
+
+	if (reg_freq->end_freq < reg_rule->end_freq)
+		reg_freq->end_freq = reg_rule->end_freq;
+}
+
 struct ieee80211_regdomain *
 ath12k_reg_build_regd(struct ath12k_base *ab,
 		      struct ath12k_reg_info *reg_info, bool intersect)
@@ -704,6 +714,7 @@  ath12k_reg_build_regd(struct ath12k_base *ab,
 			max_bw = min_t(u16, reg_rule->max_bw,
 				       reg_info->max_bw_2g);
 			flags = 0;
+			ath12k_reg_update_freq_range(&ab->reg_freq_2ghz, reg_rule);
 		} else if (reg_info->num_5g_reg_rules &&
 			   (j < reg_info->num_5g_reg_rules)) {
 			reg_rule = reg_info->reg_rules_5g_ptr + j++;
@@ -717,6 +728,7 @@  ath12k_reg_build_regd(struct ath12k_base *ab,
 			 * per other BW rule flags we pass from here
 			 */
 			flags = NL80211_RRF_AUTO_BW;
+			ath12k_reg_update_freq_range(&ab->reg_freq_5ghz, reg_rule);
 		} else if (reg_info->is_ext_reg_event &&
 			   reg_info->num_6g_reg_rules_ap[WMI_REG_INDOOR_AP] &&
 			(k < reg_info->num_6g_reg_rules_ap[WMI_REG_INDOOR_AP])) {
@@ -724,6 +736,7 @@  ath12k_reg_build_regd(struct ath12k_base *ab,
 			max_bw = min_t(u16, reg_rule->max_bw,
 				       reg_info->max_bw_6g_ap[WMI_REG_INDOOR_AP]);
 			flags = NL80211_RRF_AUTO_BW;
+			ath12k_reg_update_freq_range(&ab->reg_freq_6ghz, reg_rule);
 		} else {
 			break;
 		}