diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 52d62e0563dc4..874bd3fa5263f 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -15056,28 +15056,49 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR); for_each_ar(ah, ar, i) { + struct ath12k_base *this_ab = ar->ab; + /* Apply the regd received during initialization */ ret = ath12k_regd_update(ar, true); if (ret) { - ath12k_err(ar->ab, "ath12k regd update failed: %d\n", ret); + ath12k_err(this_ab, "ath12k regd update failed: %d\n", ret); goto err_unregister_hw; } - if (ar->ab->hw_params->current_cc_support && ab->new_alpha2[0]) { + if (this_ab->hw_params->current_cc_support) { struct wmi_set_current_country_arg current_cc = {}; + struct ieee80211_regdomain *default_regd; + bool same_cc = false; + + spin_lock_bh(&this_ab->base_lock); + memcpy(¤t_cc.alpha2, this_ab->new_alpha2, 2); + spin_unlock_bh(&this_ab->base_lock); + + if (!current_cc.alpha2[0]) + goto fw_stats_init; - memcpy(¤t_cc.alpha2, ab->new_alpha2, 2); - memcpy(&ar->alpha2, ab->new_alpha2, 2); + memcpy(&ar->alpha2, current_cc.alpha2, 2); + + spin_lock_bh(&this_ab->base_lock); + default_regd = this_ab->default_regd[ar->pdev_idx]; + if (default_regd) + same_cc = !memcmp(default_regd->alpha2, + current_cc.alpha2, 2); + spin_unlock_bh(&this_ab->base_lock); + + if (same_cc) + goto fw_stats_init; reinit_completion(&ar->regd_update_completed); ret = ath12k_wmi_send_set_current_country_cmd(ar, ¤t_cc); if (ret) - ath12k_warn(ar->ab, + ath12k_warn(this_ab, "failed set cc code for mac register: %d\n", ret); } +fw_stats_init: ath12k_fw_stats_init(ar); ath12k_debugfs_register(ar); } diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index fd9caf9f65fdb..ac1427b7b8187 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -6964,6 +6964,14 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk goto mem_free; } + /* + * Set the valid pdev_idx before validating so that, even when the + * event is dropped or falls back, the completion the caller in + * ath12k_mac_hw_register() may be waiting on is still signalled at + * the end and it does not time out. + */ + pdev_idx = reg_info->phy_id; + ret = ath12k_reg_validate_reg_info(ab, reg_info); if (ret == ATH12K_REG_STATUS_FALLBACK) { ath12k_warn(ab, "failed to validate reg info %d\n", ret); @@ -6980,7 +6988,6 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk } /* free old reg_info if it exist */ - pdev_idx = reg_info->phy_id; if (ab->reg_info[pdev_idx]) { ath12k_reg_reset_reg_info(ab->reg_info[pdev_idx]); kfree(ab->reg_info[pdev_idx]); @@ -7019,7 +7026,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk out: /* In some error cases, even a valid pdev_idx might not be available */ - if (pdev_idx != 255) + if (pdev_idx < ab->num_radios) ar = ab->pdevs[pdev_idx].ar; /* During the boot-time update, 'ar' might not be allocated,