diff options
-rw-r--r-- | package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch b/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch new file mode 100644 index 0000000000..31a7baeee7 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch @@ -0,0 +1,183 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -1238,6 +1238,8 @@ void rt2800_watchdog(struct rt2x00_dev * + 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: +@@ -1274,6 +1276,18 @@ void rt2800_watchdog(struct rt2x00_dev * + } + EXPORT_SYMBOL_GPL(rt2800_watchdog); + ++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); ++} ++EXPORT_SYMBOL_GPL(rt2800_update_survey); ++ + static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, + unsigned int index) + { +@@ -12199,26 +12213,30 @@ int rt2800_get_survey(struct ieee80211_h + { + 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); +- +- if (idle || 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->channel = &rt2x00dev->bands[band].channels[idx]; ++ ++ survey->filled = SURVEY_INFO_TIME | ++ SURVEY_INFO_TIME_BUSY | ++ SURVEY_INFO_TIME_EXT_BUSY; ++ ++ 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; +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +@@ -243,6 +243,7 @@ bool rt2800_txstatus_timeout(struct rt2x + bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev); + + void rt2800_watchdog(struct rt2x00_dev *rt2x00dev); ++void rt2800_update_survey(struct rt2x00_dev *rt2x00dev); + + void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); + void rt2800_clear_beacon(struct queue_entry *entry); +--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +@@ -360,6 +360,7 @@ static const struct rt2x00lib_ops rt2800 + .gain_calibration = rt2800_gain_calibration, + .vco_calibration = rt2800_vco_calibration, + .watchdog = rt2800_watchdog, ++ .update_survey = rt2800_update_survey, + .start_queue = rt2800mmio_start_queue, + .kick_queue = rt2800mmio_kick_queue, + .stop_queue = rt2800mmio_stop_queue, +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -214,6 +214,7 @@ static const struct rt2x00lib_ops rt2800 + .gain_calibration = rt2800_gain_calibration, + .vco_calibration = rt2800_vco_calibration, + .watchdog = rt2800_watchdog, ++ .update_survey = rt2800_update_survey, + .start_queue = rt2800mmio_start_queue, + .kick_queue = rt2800mmio_kick_queue, + .stop_queue = rt2800mmio_stop_queue, +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -183,6 +183,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 { +@@ -567,6 +576,7 @@ struct rt2x00lib_ops { + * Data queue handlers. + */ + void (*watchdog) (struct rt2x00_dev *rt2x00dev); ++ void (*update_survey) (struct rt2x00_dev *rt2x00dev); + void (*start_queue) (struct data_queue *queue); + void (*kick_queue) (struct data_queue *queue); + void (*stop_queue) (struct data_queue *queue); +@@ -755,6 +765,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; + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1057,6 +1057,12 @@ static int rt2x00lib_probe_hw_modes(stru + if (!rates) + goto exit_free_channels; + ++ rt2x00dev->chan_survey = ++ kcalloc(spec->num_channels, sizeof(struct rt2x00_chan_survey), ++ GFP_KERNEL); ++ if (!rt2x00dev->chan_survey) ++ goto exit_free_rates; ++ + /* + * Initialize Rate list. + */ +@@ -1108,6 +1114,8 @@ static int rt2x00lib_probe_hw_modes(stru + + return 0; + ++ exit_free_rates: ++ kfree(rates); + exit_free_channels: + kfree(channels); + rt2x00_err(rt2x00dev, "Allocation ieee80211 modes failed\n"); +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c +@@ -317,6 +317,15 @@ int rt2x00mac_config(struct ieee80211_hw + return 0; + + /* ++ * To provide correct survey data for survey-based ACS algorithm ++ * we have to save survey data for current channel before switching. ++ */ ++ if (rt2x00dev->ops->lib->update_survey && ++ (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { ++ rt2x00dev->ops->lib->update_survey(rt2x00dev); ++ } ++ ++ /* + * Some configuration parameters (e.g. channel and antenna values) can + * only be set when the radio is enabled, but do require the RX to + * be off. During this period we should keep link tuning enabled, |