@@ -632,6 +632,8 @@ struct ath12k_hw {
u8 num_radio;
+ bool regd_updated;
+ bool use_6ghz_regd;
/* Keep last */
struct ath12k radio[] __aligned(sizeof(void *));
};
@@ -7829,6 +7829,7 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
struct ath12k_wmi_hal_reg_capabilities_ext_arg *reg_cap;
void *channels;
u32 phy_id;
+ struct ath12k_hw *ah = ar->ah;
BUILD_BUG_ON((ARRAY_SIZE(ath12k_2ghz_channels) +
ARRAY_SIZE(ath12k_5ghz_channels) +
@@ -7881,6 +7882,7 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
ath12k_mac_update_ch_list(ar, band,
reg_cap->low_5ghz_chan,
reg_cap->high_5ghz_chan);
+ ah->use_6ghz_regd = true;
}
if (reg_cap->low_5ghz_chan < ATH12K_MIN_6G_FREQ) {
@@ -50,7 +50,7 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
struct ath12k_wmi_init_country_arg arg;
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
- int ret;
+ int ret, i;
ath12k_dbg(ar->ab, ATH12K_DBG_REG,
"Regulatory Notification received for %s\n", wiphy_name(wiphy));
@@ -85,10 +85,17 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
memcpy(&arg.cc_info.alpha2, request->alpha2, 2);
arg.cc_info.alpha2[2] = 0;
- ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
- if (ret)
- ath12k_warn(ar->ab,
- "INIT Country code set to fw failed : %d\n", ret);
+ /* Allow fresh updates to wiphy regd */
+ ah->regd_updated = false;
+
+ /* Send the reg change request to all the radios */
+ for (i = 0; i < ah->num_radio; i++) {
+ ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "INIT Country code set to fw failed : %d\n", ret);
+ ar++;
+ }
}
int ath12k_reg_update_chan_list(struct ath12k *ar)
@@ -205,8 +212,29 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
struct ieee80211_regdomain *regd, *regd_copy = NULL;
int ret, regd_len, pdev_id;
struct ath12k_base *ab;
+ int i;
ab = ar->ab;
+
+ /* If one of the radios within ah has already updated the regd for
+ * the wiphy, then avoid setting regd again
+ */
+ if (ah->regd_updated)
+ return 0;
+
+ /* firmware provides reg rules which are similar for 2 GHz and 5 GHz
+ * pdev but 6 GHz pdev has superset of all rules including rules for
+ * all bands, we prefer 6 GHz pdev's rules to be used for setup of
+ * the wiphy regd.
+ * If 6 GHz pdev was part of the ath12k_hw, wait for the 6 GHz pdev,
+ * else pick the first pdev which calls this function and use its
+ * regd to update global hw regd.
+ * The regd_updated flag set at the end will not allow any further
+ * updates.
+ */
+ if (ah->use_6ghz_regd && !ar->supports_6ghz)
+ return 0;
+
pdev_id = ar->pdev_idx;
spin_lock_bh(&ab->base_lock);
@@ -259,10 +287,22 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
if (ret)
goto err;
- if (ah->state == ATH12K_HW_STATE_ON) {
- ret = ath12k_reg_update_chan_list(ar);
- if (ret)
- goto err;
+ ah->regd_updated = true;
+
+ /* Apply the new regd to all the radios, this is expected to be received only once
+ * since we check for ah->regd_updated and allow here only once
+ */
+ ar = ah->radio;
+ ab = ar->ab;
+
+ for (i = 0; i < ah->num_radio; i++) {
+ if (ah->state == ATH12K_HW_STATE_ON) {
+ ret = ath12k_reg_update_chan_list(ar);
+ if (ret)
+ goto err;
+ }
+ ar++;
+ ab = ar->ab;
}
return 0;