[openwrt/openwrt] mac80211: rt2x00: save survey for every channel visited

LEDE Commits lede-commits at lists.infradead.org
Wed Oct 21 10:24:53 EDT 2020


dangole pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/610843f3bc72d2a7c32fbb7c61d0c4416a88d1d9

commit 610843f3bc72d2a7c32fbb7c61d0c4416a88d1d9
Author: Markov Mikhail <markov.mikhail at itmh.ru>
AuthorDate: Mon Oct 12 14:46:43 2020 +0500

    mac80211: rt2x00: save survey for every channel visited
    
    rt2800 olny gives you survey for current channel.
    
    Survey-based ACS algorithms are failing to perform their job when working
    with rt2800.
    
    Make rt2800 save survey for every channel visited and be able to give away
    that information.
    
    There is a bug registred https://dev.archive.openwrt.org/ticket/19081 and
    this patch solves the issue.
    
    Signed-off-by: Markov Mikhail <markov.mikhail at itmh.ru>
---
 ...x00-save-survey-for-every-channel-visited.patch | 183 +++++++++++++++++++++
 1 file changed, 183 insertions(+)

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,



More information about the lede-commits mailing list