diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 82617579d910..fc3fcd3c3ec8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2435,7 +2435,9 @@ struct ieee80211_sta_aggregates {
  *	notifications and capabilities. The value is only valid after
  *	the station moves to associated state.
  * @txpwr: the station tx power configuration
- *
+ * @punctured: Preamble puncturing bitmap. Each bit represents
+ *	a 20 MHz channel, lowest bit corresponding to the lowest channel.
+ *	Bit set to 1 indicates that the channel is punctured.
  */
 struct ieee80211_link_sta {
 	struct ieee80211_sta *sta;
@@ -2456,6 +2458,7 @@ struct ieee80211_link_sta {
 	u8 rx_nss;
 	enum ieee80211_sta_rx_bandwidth bandwidth;
 	struct ieee80211_sta_txpwr txpwr;
+	u16 punctured;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d9d88f2f2831..8caedd353796 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1948,13 +1948,30 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
 						  (void *)params->he_6ghz_capa,
 						  link_sta);
 
-	if (params->he_capa && params->eht_capa)
+	if (params->he_capa && params->eht_capa) {
 		ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband,
 						    (u8 *)params->he_capa,
 						    params->he_capa_len,
 						    params->eht_capa,
 						    params->eht_capa_len,
 						    link_sta);
+		/* 802.11s mesh STA may have different eht puncturing pattern,
+		 * update it here so that drivers can use if needed.
+		 */
+		if (ieee80211_vif_is_mesh(&sdata->vif) && params->punctured) {
+			struct cfg80211_chan_def chandef;
+			struct ieee80211_channel *chan = link->conf->chanreq.oper.chan;
+
+			cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
+			chandef.punctured = params->punctured;
+			chandef.width = link->conf->chanreq.oper.width;
+			chandef.width = link->conf->chanreq.oper.width;
+			chandef.center_freq1 = link->conf->chanreq.oper.center_freq1;
+
+			if (cfg80211_chandef_valid(&chandef))
+				link_sta->pub->punctured = params->punctured;
+		}
+	}
 
 	ieee80211_sta_init_nss(link_sta);
 
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 5cc56d578048..1edb4bc9d635 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -112,6 +112,12 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
 				       ie->eht_operation,
 				       &sta_chan_def);
 
+	/* In order to allow mesh peering when peer advertising different
+	 * puncturing bitmaps, update the local mesh punctured bitmap
+	 * with the new mesh peer punctured bitmap to ensure compatibility.
+	 */
+	sta_chan_def.punctured = sdata->vif.bss_conf.chanreq.oper.punctured;
+
 	if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chanreq.oper,
 					 &sta_chan_def))
 		return false;
@@ -672,6 +678,9 @@ int mesh_add_eht_oper_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *sk
 	len = 2 + 1 + offsetof(struct ieee80211_eht_operation, optional) +
 		      offsetof(struct ieee80211_eht_operation_info, optional);
 
+	if (sdata->vif.bss_conf.chanreq.oper.punctured)
+		len += sizeof(sdata->vif.bss_conf.chanreq.oper.punctured);
+
 	if (skb_tailroom(skb) < len)
 		return -ENOMEM;
 
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 9c6a2b342170..5fde9d6ec1f1 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -430,11 +430,49 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_supported_band *sband;
 	u32 rates, changed = 0;
 	enum ieee80211_sta_rx_bandwidth bw = sta->sta.deflink.bandwidth;
+	struct cfg80211_chan_def eht_chandef;
 
 	sband = ieee80211_get_sband(sdata);
 	if (!sband)
 		return;
 
+	/* 802.11s mesh peer may have different eht puncturing pattern,
+	 * update it here so that drivers can use if needed.
+	 */
+	if (elems->eht_operation &&
+	    (elems->eht_operation->params & IEEE80211_EHT_OPER_INFO_PRESENT) &&
+	    (u8_get_bits(elems->eht_operation->optional[0],
+			 IEEE80211_EHT_OPER_CHAN_WIDTH) >=
+	     IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ) &&
+	    (elems->eht_operation->params &
+	     IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT)) {
+		struct ieee80211_channel *chan = sdata->vif.bss_conf.chanreq.oper.chan;
+
+		cfg80211_chandef_create(&eht_chandef, chan, NL80211_CHAN_NO_HT);
+		eht_chandef.punctured = (elems->eht_operation->optional[4] << 8) |
+					 elems->eht_operation->optional[3];
+		/* Validate Peer's Puncturing Bitmap and reset if invalid */
+		switch (u8_get_bits(elems->eht_operation->optional[0],
+				    IEEE80211_EHT_OPER_CHAN_WIDTH)) {
+		case IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ:
+			eht_chandef.width = NL80211_CHAN_WIDTH_80;
+			break;
+		case IEEE80211_EHT_OPER_CHAN_WIDTH_160MHZ:
+			eht_chandef.width = NL80211_CHAN_WIDTH_160;
+			break;
+		case IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ:
+			eht_chandef.width = NL80211_CHAN_WIDTH_320;
+			break;
+		default:
+			eht_chandef.width = NL80211_CHAN_WIDTH_20;
+		}
+		eht_chandef.center_freq1 =
+			ieee80211_channel_to_frequency(elems->eht_operation->optional[1],
+						       chan->band);
+		if (cfg80211_chandef_valid(&eht_chandef))
+			sta->sta.deflink.punctured = eht_chandef.punctured;
+	}
+
 	rates = ieee80211_sta_get_rates(sdata, elems, sband->band, NULL);
 
 	spin_lock_bh(&sta->mesh->plink_lock);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 27d414efa3fd..442def202cad 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2850,9 +2850,13 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, const struct cfg80211_chan_def *chandef
 	u8 eht_oper_info_len =
 		offsetof(struct ieee80211_eht_operation_info, optional);
 	u8 chan_width = 0;
+	u8 ie_len = 0;
+
+	if (chandef->punctured)
+		ie_len += sizeof(chandef->punctured);
 
 	*pos++ = WLAN_EID_EXTENSION;
-	*pos++ = 1 + eht_oper_len + eht_oper_info_len;
+	*pos++ = 1 + eht_oper_len + eht_oper_info_len + ie_len;
 	*pos++ = WLAN_EID_EXT_EHT_OPERATION;
 
 	eht_oper = (struct ieee80211_eht_operation *)pos;
@@ -2904,7 +2908,14 @@ u8 *ieee80211_ie_build_eht_oper(u8 *pos, const struct cfg80211_chan_def *chandef
 	eht_oper_info->control = chan_width;
 	pos += eht_oper_info_len;
 
-	/* TODO: eht_oper_info->optional */
+	if (chandef->punctured) {
+		eht_oper->params |=
+			IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT;
+
+		eht_oper_info->optional[0] = chandef->punctured & 0x00FF;
+		eht_oper_info->optional[1] = chandef->punctured >> 8;
+		pos += sizeof(chandef->punctured);
+	}
 
 	return pos;
 }
