diff options
Diffstat (limited to 'drivers/net/wireless/ralink')
-rw-r--r-- | drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 62 | ||||
-rw-r--r-- | drivers/net/wireless/ralink/rt2x00/rt2x00.h | 10 |
2 files changed, 56 insertions, 16 deletions
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index fed6d21cd6ce..5264b0a1f098 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -1228,6 +1228,17 @@ static int rt2800_check_hung(struct data_queue *queue) 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; @@ -1237,6 +1248,8 @@ void rt2800_watchdog(struct rt2x00_dev *rt2x00dev) 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: @@ -5553,6 +5566,12 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev, 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, @@ -10111,12 +10130,20 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) } /* - * 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); @@ -10503,27 +10530,30 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx, 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; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 780be81863b6..9f6fc40649be 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -182,6 +182,15 @@ struct rf_channel { }; /* + * Information structure for channel survey. + */ +struct rt2x00_chan_survey { + u64 time_idle; + u64 time_busy; + u64 time_ext_busy; +}; + +/* * Channel information structure */ struct channel_info { @@ -752,6 +761,7 @@ struct rt2x00_dev { */ struct ieee80211_hw *hw; struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; + struct rt2x00_chan_survey *chan_survey; enum nl80211_band curr_band; int curr_freq; |