@@ -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 *));
};
@@ -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);
}
}
@@ -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;
}