diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
index 3bed5f68cd6b583fff52e9fce5227353e5e5a766..e3ad475328526cf6e9e5e312c7953f661a1e5e8d 100644
--- a/drivers/net/wireless/ath/ath12k/reg.c
+++ b/drivers/net/wireless/ath/ath12k/reg.c
@@ -949,14 +949,10 @@ void ath12k_reg_reset_reg_info(struct ath12k_reg_info *reg_info)
 	}
 }
 
-int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
-				struct ath12k_reg_info *reg_info,
-				enum wmi_vdev_type vdev_type,
-				enum ieee80211_ap_reg_power power_type)
+enum ath12k_reg_status ath12k_reg_validate_reg_info(struct ath12k_base *ab,
+						    struct ath12k_reg_info *reg_info)
 {
-	struct ieee80211_regdomain *regd = NULL;
-	struct ath12k *ar;
-	int pdev_idx;
+	int pdev_idx = reg_info->phy_id;
 
 	if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
 		/* In case of failure to set the requested country,
@@ -964,10 +960,9 @@ int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
 		 * and return from here.
 		 */
 		ath12k_warn(ab, "Failed to set the requested Country regulatory setting\n");
-		return 0;
+		return ATH12K_REG_STATUS_DROP;
 	}
 
-	pdev_idx = reg_info->phy_id;
 	if (pdev_idx >= ab->num_radios) {
 		/* Process the event for phy0 only if single_pdev_only
 		 * is true. If pdev_idx is valid but not 0, discard the
@@ -975,9 +970,9 @@ int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
 		 */
 		if (ab->hw_params->single_pdev_only &&
 		    pdev_idx < ab->hw_params->num_rxdma_per_pdev)
-			return 0;
+			return ATH12K_REG_STATUS_DROP;
 		else
-			return -EINVAL;
+			return ATH12K_REG_STATUS_FALLBACK;
 	}
 
 	/* Avoid multiple overwrites to default regd, during core
@@ -986,7 +981,19 @@ int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
 	if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
 	    !memcmp(ab->default_regd[pdev_idx]->alpha2,
 		    reg_info->alpha2, 2))
-		return 0;
+		return ATH12K_REG_STATUS_DROP;
+
+	return ATH12K_REG_STATUS_VALID;
+}
+
+int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
+				struct ath12k_reg_info *reg_info,
+				enum wmi_vdev_type vdev_type,
+				enum ieee80211_ap_reg_power power_type)
+{
+	struct ieee80211_regdomain *regd = NULL;
+	int pdev_idx = reg_info->phy_id;
+	struct ath12k *ar;
 
 	regd = ath12k_reg_build_regd(ab, reg_info, vdev_type, power_type);
 	if (!regd)
diff --git a/drivers/net/wireless/ath/ath12k/reg.h b/drivers/net/wireless/ath/ath12k/reg.h
index 9868daf3f1e56a4e112751b971d92fdad241427e..8af8e9ba462e90db3eb137885d0acd4b1cb2286e 100644
--- a/drivers/net/wireless/ath/ath12k/reg.h
+++ b/drivers/net/wireless/ath/ath12k/reg.h
@@ -92,6 +92,12 @@ enum ath12k_reg_phy_bitmap {
 	ATH12K_REG_PHY_BITMAP_NO11BE	= BIT(6),
 };
 
+enum ath12k_reg_status {
+	ATH12K_REG_STATUS_VALID,
+	ATH12K_REG_STATUS_DROP,
+	ATH12K_REG_STATUS_FALLBACK,
+};
+
 void ath12k_reg_init(struct ieee80211_hw *hw);
 void ath12k_reg_free(struct ath12k_base *ab);
 void ath12k_regd_update_work(struct work_struct *work);
@@ -109,4 +115,6 @@ int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
 				enum ieee80211_ap_reg_power power_type);
 enum wmi_reg_6g_ap_type
 ath12k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type);
+enum ath12k_reg_status ath12k_reg_validate_reg_info(struct ath12k_base *ab,
+						    struct ath12k_reg_info *reg_info);
 #endif
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index be66e88fb65a92f943f86c5fa597f13953aa02b2..42e275762563f84f4891ffd1be8e33917f1192d2 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -6129,7 +6129,22 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
 	ret = ath12k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
 	if (ret) {
 		ath12k_warn(ab, "failed to extract regulatory info from received event\n");
-		goto fallback;
+		goto mem_free;
+	}
+
+	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);
+		/* firmware has successfully switches to new regd but host can not
+		 * continue, so free reginfo and fallback to old regd
+		 */
+		goto mem_free;
+	} else if (ret == ATH12K_REG_STATUS_DROP) {
+		/* reg info is valid but we will not store it and
+		 * not going to create new regd for it
+		 */
+		ret = ATH12K_REG_STATUS_VALID;
+		goto mem_free;
 	}
 
 	ret = ath12k_reg_handle_chan_list(ab, reg_info, WMI_VDEV_TYPE_UNSPEC,
@@ -6139,7 +6154,14 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
 		goto fallback;
 	}
 
-	goto mem_free;
+	goto out;
+
+mem_free:
+	ath12k_reg_reset_reg_info(reg_info);
+	kfree(reg_info);
+
+	if (ret == ATH12K_REG_STATUS_VALID)
+		return ret;
 
 fallback:
 	/* Fallback to older reg (by sending previous country setting
@@ -6152,12 +6174,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
 	/* TODO: This is rare, but still should also be handled */
 	WARN_ON(1);
 
-mem_free:
-	if (reg_info) {
-		ath12k_reg_reset_reg_info(reg_info);
-		kfree(reg_info);
-	}
-
+out:
 	return ret;
 }
 
