diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a823b34120aa..4675a6feb09b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -512,6 +512,21 @@ struct ieee80211_sta_s1g_cap {
 	u8 nss_mcs[5];
 };
 
+/**
+ * struct ieee80211_channel_6ghz - 6 GHz channel definitions
+ *
+ * This structure defines all the channels supported by the
+ * 6 GHz band.
+ *
+ * @channels: Array of channels the hardware can operate with
+ *      in 6 GHz band.
+ * @n_channels: Number of channels in @channels
+ */
+struct ieee80211_channel_6ghz {
+	struct ieee80211_channel *channels;
+	int n_channels;
+};
+
 /**
  * struct ieee80211_supported_band - frequency band definition
  *
@@ -520,6 +535,7 @@ struct ieee80211_sta_s1g_cap {
  *
  * @channels: Array of channels the hardware can operate with
  *	in this band.
+ * @channels_6ghz: Array of 6 GHz channels the hardware can operate with
  * @band: the band this structure represents
  * @n_channels: Number of channels in @channels
  * @bitrates: Array of bitrates the hardware can operate with
@@ -539,6 +555,8 @@ struct ieee80211_sta_s1g_cap {
  */
 struct ieee80211_supported_band {
 	struct ieee80211_channel *channels;
+	struct ieee80211_channel_6ghz
+			    *channels_6ghz[NL80211_REG_PWR_MODE_MAX];
 	struct ieee80211_rate *bitrates;
 	enum nl80211_band band;
 	int n_channels;
@@ -6074,6 +6092,19 @@ ieee80211_get_channel(struct wiphy *wiphy, int freq)
 	return ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(freq));
 }
 
+/**
+ * ieee80211_get_6ghz_channel_khz - get channel struct from wiphy for specified
+ *                                  frequency in 6 GHz band
+ *
+ * @wiphy: the struct wiphy to get the channel for
+ * @freq: the center frequency (in KHz) of the channel
+ * @power_mode: the power mode in which freq is to be operated
+ * Return: The channel struct from @wiphy at @freq.
+ */
+struct ieee80211_channel *
+ieee80211_get_6ghz_channel_khz(struct wiphy *wiphy, u32 freq,
+			       enum nl80211_regulatory_power_modes power_mode);
+
 /**
  * cfg80211_channel_is_psc - Check if the channel is a 6 GHz PSC
  * @chan: control channel to check
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index c2bf0b39fd1e..93402ccf366c 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -221,6 +221,7 @@ struct ieee80211_reg_rule {
 	struct ieee80211_freq_range freq_range;
 	struct ieee80211_power_rule power_rule;
 	struct ieee80211_wmm_rule wmm_rule;
+	enum nl80211_regulatory_power_modes power_mode;
 	u32 flags;
 	u32 dfs_cac_ms;
 	bool has_wmm;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 1a28fe5cb614..9ddbc02571c1 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3676,6 +3676,9 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
 	bool support_80_80, support_160, support_320;
 	u8 he_phy_cap, eht_phy_cap;
 	u32 freq;
+	enum ieee80211_ap_reg_power reg_6ghz_power_beacon, reg_6ghz_ap_power;
+	enum ieee80211_client_reg_power reg_6ghz_client_power;
+	enum nl80211_regulatory_power_modes reg_6ghz_power_final;
 
 	if (chandef->chan->band != NL80211_BAND_6GHZ)
 		return true;
@@ -3718,6 +3721,39 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
 		return false;
 	}
 
+	/* 6 GHz Power mode present in the beacon */
+	reg_6ghz_power_beacon = u8_get_bits(he_6ghz_oper->control,
+					    IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO);
+	switch (reg_6ghz_power_beacon) {
+	case IEEE80211_REG_LPI_AP:
+	case IEEE80211_REG_SP_AP:
+	case IEEE80211_REG_VLP_AP:
+		break;
+	default:
+		sdata_info(sdata,
+			   "Invalid Regulatory Info subfield in HE 6 GHz operation, expect issues\n");
+		return false;
+	}
+
+	/* For AP/AP_VLAN/MESH_POINT interfaces, the 6 GHz power mode depends on the
+	 * mode configured by user (LPI/SP/VLP). For other interfaces (for ex STA)
+	 * mode depends on the power mode present in beacon as well as power mode
+	 * configured by the user for that interface
+	 */
+	if (iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_AP_VLAN ||
+	    iftype == NL80211_IFTYPE_MESH_POINT) {
+		reg_6ghz_ap_power =
+			sdata->wdev.links[bss_conf->link_id].ap.power_mode_6ghz;
+		reg_6ghz_power_final =
+			ieee80211_ap_reg_power_to_reg_power_mode(reg_6ghz_ap_power);
+	} else {
+		reg_6ghz_client_power =
+			sdata->wdev.links[bss_conf->link_id].client.power_mode_6ghz;
+		reg_6ghz_power_final =
+		     ieee80211_client_reg_power_to_reg_power_mode(reg_6ghz_client_power,
+								  reg_6ghz_power_beacon);
+	}
+
 	/*
 	 * The EHT operation IE does not contain the primary channel so the
 	 * primary channel frequency should be taken from the 6 GHz operation
@@ -3725,7 +3761,9 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
 	 */
 	freq = ieee80211_channel_to_frequency(he_6ghz_oper->primary,
 					      NL80211_BAND_6GHZ);
-	he_chandef.chan = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
+	he_chandef.chan = ieee80211_get_6ghz_channel_khz(sdata->local->hw.wiphy,
+							 MHZ_TO_KHZ(freq),
+							 reg_6ghz_power_final);
 
 	switch (u8_get_bits(he_6ghz_oper->control,
 			    IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO)) {
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 452e0085ed2c..c5bf3c9abdb1 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1594,7 +1594,8 @@ static u32 map_regdom_flags(u32 rd_flags)
 
 static const struct ieee80211_reg_rule *
 freq_reg_info_regd(u32 center_freq,
-		   const struct ieee80211_regdomain *regd, u32 bw)
+		   const struct ieee80211_regdomain *regd, u32 bw,
+		   enum nl80211_regulatory_power_modes power_mode)
 {
 	int i;
 	bool band_rule_found = false;
@@ -1608,7 +1609,12 @@ freq_reg_info_regd(u32 center_freq,
 		const struct ieee80211_freq_range *fr = NULL;
 
 		rr = &regd->reg_rules[i];
-		fr = &rr->freq_range;
+
+		if (rr->power_mode == power_mode)
+			fr = &rr->freq_range;
+
+		if (!fr)
+			continue;
 
 		/*
 		 * We only need to know if one frequency rule was
@@ -1640,7 +1646,8 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
 	u32 bw;
 
 	for (bw = MHZ_TO_KHZ(bws[i]); bw >= min_bw; bw = MHZ_TO_KHZ(bws[i--])) {
-		reg_rule = freq_reg_info_regd(center_freq, regd, bw);
+		reg_rule = freq_reg_info_regd(center_freq, regd, bw,
+					      NL80211_REG_PWR_MODE_AP_LPI);
 		if (!IS_ERR(reg_rule))
 			return reg_rule;
 	}
@@ -2292,7 +2299,8 @@ static void reg_process_ht_flags_channel(struct wiphy *wiphy,
 	if (regd) {
 		const struct ieee80211_reg_rule *reg_rule =
 			freq_reg_info_regd(MHZ_TO_KHZ(channel->center_freq),
-					   regd, MHZ_TO_KHZ(20));
+					   regd, MHZ_TO_KHZ(20),
+					   NL80211_REG_PWR_MODE_AP_LPI);
 
 		if (!IS_ERR(reg_rule))
 			flags = reg_rule->flags;
@@ -2535,7 +2543,8 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
 static void handle_channel_custom(struct wiphy *wiphy,
 				  struct ieee80211_channel *chan,
 				  const struct ieee80211_regdomain *regd,
-				  u32 min_bw)
+				  u32 min_bw,
+				  enum nl80211_regulatory_power_modes power_mode)
 {
 	u32 bw_flags = 0;
 	const struct ieee80211_reg_rule *reg_rule = NULL;
@@ -2544,7 +2553,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
 
 	center_freq_khz = ieee80211_channel_to_khz(chan);
 	for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
-		reg_rule = freq_reg_info_regd(center_freq_khz, regd, bw);
+		reg_rule = freq_reg_info_regd(center_freq_khz, regd, bw, power_mode);
 		if (!IS_ERR(reg_rule))
 			break;
 	}
@@ -2596,11 +2605,29 @@ static void handle_band_custom(struct wiphy *wiphy,
 			       struct ieee80211_supported_band *sband,
 			       const struct ieee80211_regdomain *regd)
 {
-	unsigned int i;
+	unsigned int i, j;
+	bool channels_6ghz_present = false;
 
 	if (!sband)
 		return;
 
+	if (sband->band == NL80211_BAND_6GHZ) {
+		for (i = 0; i < NL80211_REG_PWR_MODE_MAX; i++) {
+			if (!sband->channels_6ghz[i])
+				continue;
+
+			channels_6ghz_present = true;
+
+			for (j = 0; j < sband->channels_6ghz[i]->n_channels; j++)
+				handle_channel_custom(wiphy,
+						      &sband->channels_6ghz[i]->channels[j],
+						      regd, MHZ_TO_KHZ(20), i);
+		}
+
+		if (channels_6ghz_present)
+			return;
+	}
+
 	/*
 	 * We currently assume that you always want at least 20 MHz,
 	 * otherwise channel 12 might get enabled if this rule is
@@ -2608,7 +2635,8 @@ static void handle_band_custom(struct wiphy *wiphy,
 	 */
 	for (i = 0; i < sband->n_channels; i++)
 		handle_channel_custom(wiphy, &sband->channels[i], regd,
-				      MHZ_TO_KHZ(20));
+				      MHZ_TO_KHZ(20),
+				      NL80211_REG_PWR_MODE_AP_LPI);
 }
 
 /* Used by drivers prior to wiphy registration */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 56a23e5797f4..266ce51b2f7b 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -165,6 +165,33 @@ int ieee80211_freq_khz_to_channel(u32 freq)
 }
 EXPORT_SYMBOL(ieee80211_freq_khz_to_channel);
 
+struct ieee80211_channel
+*ieee80211_get_6ghz_channel_khz(struct wiphy *wiphy, u32 freq,
+				enum nl80211_regulatory_power_modes power_mode)
+{
+	struct ieee80211_supported_band *sband;
+	int i;
+	struct ieee80211_channel *chan;
+
+	sband = wiphy->bands[NL80211_BAND_6GHZ];
+
+	if (!sband || power_mode >= NL80211_REG_PWR_MODE_MAX)
+		return NULL;
+
+	if (!sband->channels_6ghz[power_mode])
+		return ieee80211_get_channel_khz(wiphy, freq);
+
+	for (i = 0; i < sband->channels_6ghz[power_mode]->n_channels; i++) {
+		chan = &sband->channels_6ghz[power_mode]->channels[i];
+
+		if (ieee80211_channel_to_khz(chan) == freq)
+			return chan;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(ieee80211_get_6ghz_channel_khz);
+
 struct ieee80211_channel *ieee80211_get_channel_khz(struct wiphy *wiphy,
 						    u32 freq)
 {
