aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch')
-rw-r--r--package/kernel/mac80211/patches/rt2x00/992-rt2x00-save-survey-for-every-channel-visited.patch183
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,