return queue->wd_count > 16;
 }
 
+static void rt2800_update_survey(struct rt2x00_dev *rt2x00dev)
+{
+       struct ieee80211_channel *chan = rt2x00dev->hw->conf.chandef.chan;
+       struct rt2x00_chan_survey *chan_survey =
+                  &rt2x00dev->chan_survey[chan->hw_value];
+
+       chan_survey->time_idle += rt2800_register_read(rt2x00dev, CH_IDLE_STA);
+       chan_survey->time_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA);
+       chan_survey->time_ext_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
+}
+
 void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
 {
        struct data_queue *queue;
        if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
                return;
 
+       rt2800_update_survey(rt2x00dev);
+
        queue_for_each(rt2x00dev, queue) {
                switch (queue->qid) {
                case QID_AC_VO:
        rt2800_config_lna_gain(rt2x00dev, libconf);
 
        if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
+               /*
+                * To provide correct survey data for survey-based ACS algorithm
+                * we have to save survey data for current channel before switching.
+                */
+               rt2800_update_survey(rt2x00dev);
+
                rt2800_config_channel(rt2x00dev, libconf->conf,
                                      &libconf->rf, &libconf->channel);
                rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
        }
 
        /*
-        * Create channel information array
+        * Create channel information and survey arrays
         */
        info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
+       rt2x00dev->chan_survey =
+               kcalloc(spec->num_channels, sizeof(struct rt2x00_chan_survey),
+                       GFP_KERNEL);
+       if (!rt2x00dev->chan_survey) {
+               kfree(info);
+               return -ENOMEM;
+       }
+
        spec->channels_info = info;
 
        default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
                      struct survey_info *survey)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_conf *conf = &hw->conf;
-       u32 idle, busy, busy_ext;
+       struct rt2x00_chan_survey *chan_survey =
+                  &rt2x00dev->chan_survey[idx];
+       enum nl80211_band band = NL80211_BAND_2GHZ;
 
-       if (idx != 0)
+       if (idx >= rt2x00dev->bands[band].n_channels) {
+               idx -= rt2x00dev->bands[band].n_channels;
+               band = NL80211_BAND_5GHZ;
+       }
+
+       if (idx >= rt2x00dev->bands[band].n_channels)
                return -ENOENT;
 
-       survey->channel = conf->chandef.chan;
+       if (idx == 0)
+               rt2800_update_survey(rt2x00dev);
 
-       idle = rt2800_register_read(rt2x00dev, CH_IDLE_STA);
-       busy = rt2800_register_read(rt2x00dev, CH_BUSY_STA);
-       busy_ext = rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
+       survey->channel = &rt2x00dev->bands[band].channels[idx];
 
-       if (idle || busy) {
-               survey->filled = SURVEY_INFO_TIME |
-                                SURVEY_INFO_TIME_BUSY |
-                                SURVEY_INFO_TIME_EXT_BUSY;
+       survey->filled = SURVEY_INFO_TIME |
+                        SURVEY_INFO_TIME_BUSY |
+                        SURVEY_INFO_TIME_EXT_BUSY;
 
-               survey->time = (idle + busy) / 1000;
-               survey->time_busy = busy / 1000;
-               survey->time_ext_busy = busy_ext / 1000;
-       }
+       survey->time = div_u64(chan_survey->time_idle + chan_survey->time_busy, 1000);
+       survey->time_busy = div_u64(chan_survey->time_busy, 1000);
+       survey->time_ext_busy = div_u64(chan_survey->time_ext_busy, 1000);
 
        if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
                survey->filled |= SURVEY_INFO_IN_USE;