mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-19 13:48:06 +00:00
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@itmh.ru>
This commit is contained in:
parent
b90a4a8e08
commit
610843f3bc
@ -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,
|
Loading…
Reference in New Issue
Block a user