INIT_LIST_HEAD(&wcn->vif_list);
        spin_lock_init(&wcn->dxe_lock);
+       spin_lock_init(&wcn->survey_lock);
 
        return 0;
 
        struct wcn36xx_vif *tmp;
        struct ieee80211_supported_band *band;
        struct ieee80211_channel *channel;
+       unsigned long flags;
        int i, j;
 
        for (i = 0; i < ARRAY_SIZE(wcn->hw->wiphy->bands); i++) {
                return;
        }
 
+       spin_lock_irqsave(&wcn->survey_lock, flags);
        wcn->band = band;
        wcn->channel = channel;
+       spin_unlock_irqrestore(&wcn->survey_lock, flags);
 
        list_for_each_entry(tmp, &wcn->vif_list, list) {
                vif = wcn36xx_priv_to_vif(tmp);
        void *wcnss;
        int ret;
        const u8 *addr;
+       int n_channels;
 
        wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
 
                goto out_wq;
        }
 
+       n_channels = wcn_band_2ghz.n_channels + wcn_band_5ghz.n_channels;
+       wcn->chan_survey = devm_kmalloc(wcn->dev, n_channels, GFP_KERNEL);
+       if (!wcn->chan_survey) {
+               ret = -ENOMEM;
+               goto out_wq;
+       }
+
        ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
        if (ret < 0) {
                wcn36xx_err("failed to set DMA mask: %d\n", ret);
 
                dev_kfree_skb_irq(skb);
 }
 
+static void wcn36xx_update_survey(struct wcn36xx *wcn, int rssi, int snr,
+                                 int band, int freq)
+{
+       static struct ieee80211_channel *channel;
+       struct ieee80211_supported_band *sband;
+       int idx;
+       int i;
+
+       idx = 0;
+       if (band == NL80211_BAND_5GHZ)
+               idx = wcn->hw->wiphy->bands[NL80211_BAND_2GHZ]->n_channels;
+
+       sband = wcn->hw->wiphy->bands[band];
+       channel = sband->channels;
+
+       for (i = 0; i < sband->n_channels; i++, channel++) {
+               if (channel->center_freq == freq) {
+                       idx += i;
+                       break;
+               }
+       }
+
+       spin_lock(&wcn->survey_lock);
+       wcn->chan_survey[idx].rssi = rssi;
+       wcn->chan_survey[idx].snr = snr;
+       spin_unlock(&wcn->survey_lock);
+}
+
 int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
 {
        struct ieee80211_rx_status status;
                status.freq = WCN36XX_CENTER_FREQ(wcn);
        }
 
+        wcn36xx_update_survey(wcn, status.signal, get_snr(bd),
+                              status.band, status.freq);
+
        if (bd->rate_id < ARRAY_SIZE(wcn36xx_rate_table)) {
                rate = &wcn36xx_rate_table[bd->rate_id];
                status.encoding = rate->encoding;
 
        enum wcn36xx_ampdu_state ampdu_state[16];
        int non_agg_frame_ct;
 };
+
 struct wcn36xx_dxe_ch;
+
+struct wcn36xx_chan_survey {
+       s8      rssi;
+       u8      snr;
+};
+
 struct wcn36xx {
        struct ieee80211_hw     *hw;
        struct device           *dev;
 
        struct ieee80211_supported_band *band;
        struct ieee80211_channel *channel;
+
+       spinlock_t survey_lock;         /* protects chan_survey */
+       struct wcn36xx_chan_survey      *chan_survey;
 };
 
 static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,