diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 3385a2cc5b09..f23340654ecf 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1287,6 +1287,24 @@ struct ieee80211_ttlm_elem {
 	u8 optional[];
 } __packed;
 
+/**
+ * struct ieee80211_bss_load_elem - BSS Load elemen
+ *
+ * Defined in section 9.4.2.26 in IEEE 802.11-REVme D4.1
+ *
+ * @sta_count: total number of STAs currently associated with the AP.
+ * @channel_util: Percentage of time that the access point sensed the channel
+ *	was busy. This value is in range [0, 255], the highest value means
+ *	100% busy.
+ * @avail_admission_capa: remaining amount of medium time used for admission
+ *	control.
+ */
+struct ieee80211_bss_load_elem {
+	__le16 sta_count;
+	u8 channel_util;
+	__le16 avail_admission_capa;
+} __packed;
+
 struct ieee80211_mgmt {
 	__le16 frame_control;
 	__le16 duration;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index fc223761e3af..0af80a2b6cfc 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -671,6 +671,11 @@ struct ieee80211_fils_discovery {
  *	processed after it switches back to %NULL.
  * @color_change_active: marks whether a color change is ongoing.
  * @color_change_color: the bss color that will be used after the change.
+ * @channel_util: Channel utilization as published by the AP in the
+ *	WLAN_EID_QBSS_LOAD information element. An unsigned integer in the
+ *	range [0,255], when 255 means the 100% busy. Valid only for a
+ *	station, and only when associated. Will be -1 if AP didn't
+ *	send the element.
  * @ht_ldpc: in AP mode, indicates interface has HT LDPC capability.
  * @vht_ldpc: in AP mode, indicates interface has VHT LDPC capability.
  * @he_ldpc: in AP mode, indicates interface has HE LDPC capability.
@@ -774,6 +779,8 @@ struct ieee80211_bss_conf {
 	bool color_change_active;
 	u8 color_change_color;
 
+	s16 channel_util;
+
 	bool ht_ldpc;
 	bool vht_ldpc;
 	bool he_ldpc;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f3edb1a148a7..7bc1e55de358 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1741,6 +1741,7 @@ struct ieee802_11_elems {
 	const struct ieee80211_multi_link_elem *ml_reconf;
 	const struct ieee80211_bandwidth_indication *bandwidth_indication;
 	const struct ieee80211_ttlm_elem *ttlm[IEEE80211_TTLM_MAX_CNT];
+	const struct ieee80211_bss_load_elem *bss_load;
 
 	/* length of them, respectively */
 	u8 ext_capab_len;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2f13451ba003..8a9c9188eb65 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3078,6 +3078,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 	/* other links will be destroyed */
 	sdata->deflink.u.mgd.bss = NULL;
 	sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
+	sdata->deflink.conf->channel_util = -1;
 
 	netif_carrier_off(sdata->dev);
 
@@ -6359,6 +6360,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
 		erp_valid = false;
 	}
 
+	bss_conf->channel_util =
+		elems->bss_load ? elems->bss_load->channel_util : -1;
+
 	if (!ieee80211_is_s1g_beacon(hdr->frame_control))
 		changed |= ieee80211_handle_bss_capability(link,
 				le16_to_cpu(mgmt->u.beacon.capab_info),
@@ -7444,6 +7448,7 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link)
 	link->u.mgd.p2p_noa_index = -1;
 	link->conf->bssid = link->u.mgd.bssid;
 	link->smps_mode = IEEE80211_SMPS_OFF;
+	link->conf->channel_util = -1;
 
 	wiphy_work_init(&link->u.mgd.request_smps_work,
 			ieee80211_request_smps_mgd_work);
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index 196a882e4c19..07bb21a92360 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -203,6 +203,7 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
 		case WLAN_EID_CF_PARAMS:
 		case WLAN_EID_TIM:
 		case WLAN_EID_IBSS_PARAMS:
+		case WLAN_EID_QBSS_LOAD:
 		case WLAN_EID_CHALLENGE:
 		case WLAN_EID_RSN:
 		case WLAN_EID_ERP_INFO:
@@ -297,6 +298,13 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
 				elem_parse_failed =
 					IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
 			break;
+		case WLAN_EID_QBSS_LOAD:
+			if (elen == sizeof(struct ieee80211_bss_load_elem))
+				elems->bss_load = (void *)pos;
+			else
+				elem_parse_failed =
+					IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
+			break;
 		case WLAN_EID_VENDOR_SPECIFIC:
 			if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
 			    pos[2] == 0xf2) {
