diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fc40843..e0ecd7d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -580,6 +580,7 @@ ieee80211_chandef_max_power(struct cfg80211_chan_def *chandef)
  * @SURVEY_INFO_TIME_RX: receive time was filled in
  * @SURVEY_INFO_TIME_TX: transmit time was filled in
  * @SURVEY_INFO_TIME_SCAN: scan time was filled in
+ * @SURVEY_INFO_NON_ACC_DATA: non accumulated survey data filled in
  *
  * Used by the driver to indicate which info in &struct survey_info
  * it has filled in during the get_survey().
@@ -593,6 +594,7 @@ enum survey_info_flags {
 	SURVEY_INFO_TIME_RX		= BIT(5),
 	SURVEY_INFO_TIME_TX		= BIT(6),
 	SURVEY_INFO_TIME_SCAN		= BIT(7),
+	SURVEY_INFO_NON_ACC_DATA        = BIT(8),
 };
 
 /**
@@ -3787,6 +3789,7 @@ struct wiphy_iftype_ext_capab {
  *	bitmap of &enum nl80211_band values.  For instance, for
  *	NL80211_BAND_2GHZ, bit 0 would be set
  *	(i.e. BIT(NL80211_BAND_2GHZ)).
+ * @cumulative_survey: cumulated survey information for all channels.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -3921,6 +3924,8 @@ struct wiphy {
 
 	u8 nan_supported_bands;
 
+	struct survey_info *cumulative_survey;
+
 	char priv[0] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 670aa229..4646769 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -633,6 +633,9 @@ int wiphy_register(struct wiphy *wiphy)
 	struct ieee80211_supported_band *sband;
 	bool have_band = false;
 	int i;
+	int n_channels = 0;
+	int idx = 0;
+
 	u16 ifmodes = wiphy->interface_modes;
 
 #ifdef CONFIG_PM
@@ -782,6 +785,7 @@ int wiphy_register(struct wiphy *wiphy)
 		}
 
 		have_band = true;
+		n_channels += sband->n_channels;
 	}
 
 	if (!have_band) {
@@ -866,6 +870,21 @@ int wiphy_register(struct wiphy *wiphy)
 		}
 	}
 
+	wiphy->cumulative_survey = kcalloc(n_channels,
+					   sizeof(struct survey_info),
+					   GFP_KERNEL);
+	if (!wiphy->cumulative_survey)
+		return -ENOMEM;
+
+	for (band = 0; band < NUM_NL80211_BANDS; band++) {
+		sband = wiphy->bands[band];
+		if (!sband)
+			continue;
+		for (i = 0; i < sband->n_channels; i++)
+			wiphy->cumulative_survey[idx++].channel =
+				&sband->channels[i];
+	}
+
 	rdev->wiphy.registered = true;
 	rtnl_unlock();
 
@@ -955,6 +974,8 @@ void wiphy_unregister(struct wiphy *wiphy)
 #endif
 	cfg80211_rdev_free_wowlan(rdev);
 	cfg80211_rdev_free_coalesce(rdev);
+
+	kfree(wiphy->cumulative_survey);
 }
 EXPORT_SYMBOL(wiphy_unregister);
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fe27ab4..2f22d74 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8024,11 +8024,13 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	struct nlattr **attrbuf = genl_family_attrbuf(&nl80211_fam);
 	struct survey_info survey;
+	struct survey_info *survey_data = &survey;
 	struct cfg80211_registered_device *rdev;
 	struct wireless_dev *wdev;
 	int survey_idx = cb->args[2];
 	int res;
 	bool radio_stats;
+	int n_channels;
 
 	rtnl_lock();
 	res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
@@ -8048,7 +8050,12 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
 		goto out_err;
 	}
 
+	n_channels = ieee80211_get_num_supported_channels(wdev->wiphy);
+
 	while (1) {
+		if (n_channels <= survey_idx)
+			break;
+
 		res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
 		if (res == -ENOENT)
 			break;
@@ -8062,10 +8069,35 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
 			continue;
 		}
 
+		if (survey.filled & SURVEY_INFO_NON_ACC_DATA) {
+			struct survey_info *cumulative_survey =
+				&wdev->wiphy->cumulative_survey[survey_idx];
+
+			if (cumulative_survey->channel->center_freq !=
+					survey.channel->center_freq) {
+				survey_idx++;
+				continue;
+			}
+			if (survey.filled & SURVEY_INFO_NOISE_DBM)
+				cumulative_survey->noise = survey.noise;
+			if (survey.filled & SURVEY_INFO_TIME)
+				cumulative_survey->time += survey.time;
+			if (survey.filled & SURVEY_INFO_TIME_BUSY)
+				cumulative_survey->time_busy +=
+							survey.time_busy;
+			if (survey.filled & SURVEY_INFO_TIME_RX)
+				cumulative_survey->time_rx += survey.time_rx;
+			if (survey.filled & SURVEY_INFO_TIME_TX)
+				cumulative_survey->time_tx += survey.time_tx;
+
+			cumulative_survey->filled |= survey.filled;
+			survey_data = cumulative_survey;
+		}
+
 		if (nl80211_send_survey(skb,
 				NETLINK_CB(cb->skb).portid,
 				cb->nlh->nlmsg_seq, NLM_F_MULTI,
-				wdev->netdev, radio_stats, &survey) < 0)
+				wdev->netdev, radio_stats, survey_data) < 0)
 			goto out;
 		survey_idx++;
 	}
