31a7baeee7558beb1969eb50afe54e6727dbfdaa
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / rt2x00 / 992-rt2x00-save-survey-for-every-channel-visited.patch
1 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
2 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
3 @@ -1238,6 +1238,8 @@ void rt2800_watchdog(struct rt2x00_dev *
4 if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
5 return;
6
7 + rt2800_update_survey(rt2x00dev);
8 +
9 queue_for_each(rt2x00dev, queue) {
10 switch (queue->qid) {
11 case QID_AC_VO:
12 @@ -1274,6 +1276,18 @@ void rt2800_watchdog(struct rt2x00_dev *
13 }
14 EXPORT_SYMBOL_GPL(rt2800_watchdog);
15
16 +void rt2800_update_survey(struct rt2x00_dev *rt2x00dev)
17 +{
18 + struct ieee80211_channel *chan = rt2x00dev->hw->conf.chandef.chan;
19 + struct rt2x00_chan_survey *chan_survey =
20 + &rt2x00dev->chan_survey[chan->hw_value];
21 +
22 + chan_survey->time_idle += rt2800_register_read(rt2x00dev, CH_IDLE_STA);
23 + chan_survey->time_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA);
24 + chan_survey->time_ext_busy += rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
25 +}
26 +EXPORT_SYMBOL_GPL(rt2800_update_survey);
27 +
28 static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
29 unsigned int index)
30 {
31 @@ -12199,26 +12213,30 @@ int rt2800_get_survey(struct ieee80211_h
32 {
33 struct rt2x00_dev *rt2x00dev = hw->priv;
34 struct ieee80211_conf *conf = &hw->conf;
35 - u32 idle, busy, busy_ext;
36 + struct rt2x00_chan_survey *chan_survey =
37 + &rt2x00dev->chan_survey[idx];
38 + enum nl80211_band band = NL80211_BAND_2GHZ;
39
40 - if (idx != 0)
41 + if (idx >= rt2x00dev->bands[band].n_channels) {
42 + idx -= rt2x00dev->bands[band].n_channels;
43 + band = NL80211_BAND_5GHZ;
44 + }
45 +
46 + if (idx >= rt2x00dev->bands[band].n_channels)
47 return -ENOENT;
48
49 - survey->channel = conf->chandef.chan;
50 + if (idx == 0)
51 + rt2800_update_survey(rt2x00dev);
52
53 - idle = rt2800_register_read(rt2x00dev, CH_IDLE_STA);
54 - busy = rt2800_register_read(rt2x00dev, CH_BUSY_STA);
55 - busy_ext = rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC);
56 -
57 - if (idle || busy) {
58 - survey->filled = SURVEY_INFO_TIME |
59 - SURVEY_INFO_TIME_BUSY |
60 - SURVEY_INFO_TIME_EXT_BUSY;
61 -
62 - survey->time = (idle + busy) / 1000;
63 - survey->time_busy = busy / 1000;
64 - survey->time_ext_busy = busy_ext / 1000;
65 - }
66 + survey->channel = &rt2x00dev->bands[band].channels[idx];
67 +
68 + survey->filled = SURVEY_INFO_TIME |
69 + SURVEY_INFO_TIME_BUSY |
70 + SURVEY_INFO_TIME_EXT_BUSY;
71 +
72 + survey->time = div_u64(chan_survey->time_idle + chan_survey->time_busy, 1000);
73 + survey->time_busy = div_u64(chan_survey->time_busy, 1000);
74 + survey->time_ext_busy = div_u64(chan_survey->time_ext_busy, 1000);
75
76 if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
77 survey->filled |= SURVEY_INFO_IN_USE;
78 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
79 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
80 @@ -243,6 +243,7 @@ bool rt2800_txstatus_timeout(struct rt2x
81 bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev);
82
83 void rt2800_watchdog(struct rt2x00_dev *rt2x00dev);
84 +void rt2800_update_survey(struct rt2x00_dev *rt2x00dev);
85
86 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
87 void rt2800_clear_beacon(struct queue_entry *entry);
88 --- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
89 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
90 @@ -360,6 +360,7 @@ static const struct rt2x00lib_ops rt2800
91 .gain_calibration = rt2800_gain_calibration,
92 .vco_calibration = rt2800_vco_calibration,
93 .watchdog = rt2800_watchdog,
94 + .update_survey = rt2800_update_survey,
95 .start_queue = rt2800mmio_start_queue,
96 .kick_queue = rt2800mmio_kick_queue,
97 .stop_queue = rt2800mmio_stop_queue,
98 --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
99 +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
100 @@ -214,6 +214,7 @@ static const struct rt2x00lib_ops rt2800
101 .gain_calibration = rt2800_gain_calibration,
102 .vco_calibration = rt2800_vco_calibration,
103 .watchdog = rt2800_watchdog,
104 + .update_survey = rt2800_update_survey,
105 .start_queue = rt2800mmio_start_queue,
106 .kick_queue = rt2800mmio_kick_queue,
107 .stop_queue = rt2800mmio_stop_queue,
108 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
109 +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
110 @@ -183,6 +183,15 @@ struct rf_channel {
111 };
112
113 /*
114 + * Information structure for channel survey.
115 + */
116 +struct rt2x00_chan_survey {
117 + u64 time_idle;
118 + u64 time_busy;
119 + u64 time_ext_busy;
120 +};
121 +
122 +/*
123 * Channel information structure
124 */
125 struct channel_info {
126 @@ -567,6 +576,7 @@ struct rt2x00lib_ops {
127 * Data queue handlers.
128 */
129 void (*watchdog) (struct rt2x00_dev *rt2x00dev);
130 + void (*update_survey) (struct rt2x00_dev *rt2x00dev);
131 void (*start_queue) (struct data_queue *queue);
132 void (*kick_queue) (struct data_queue *queue);
133 void (*stop_queue) (struct data_queue *queue);
134 @@ -755,6 +765,7 @@ struct rt2x00_dev {
135 */
136 struct ieee80211_hw *hw;
137 struct ieee80211_supported_band bands[NUM_NL80211_BANDS];
138 + struct rt2x00_chan_survey *chan_survey;
139 enum nl80211_band curr_band;
140 int curr_freq;
141
142 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
143 +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
144 @@ -1057,6 +1057,12 @@ static int rt2x00lib_probe_hw_modes(stru
145 if (!rates)
146 goto exit_free_channels;
147
148 + rt2x00dev->chan_survey =
149 + kcalloc(spec->num_channels, sizeof(struct rt2x00_chan_survey),
150 + GFP_KERNEL);
151 + if (!rt2x00dev->chan_survey)
152 + goto exit_free_rates;
153 +
154 /*
155 * Initialize Rate list.
156 */
157 @@ -1108,6 +1114,8 @@ static int rt2x00lib_probe_hw_modes(stru
158
159 return 0;
160
161 + exit_free_rates:
162 + kfree(rates);
163 exit_free_channels:
164 kfree(channels);
165 rt2x00_err(rt2x00dev, "Allocation ieee80211 modes failed\n");
166 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
167 +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
168 @@ -317,6 +317,15 @@ int rt2x00mac_config(struct ieee80211_hw
169 return 0;
170
171 /*
172 + * To provide correct survey data for survey-based ACS algorithm
173 + * we have to save survey data for current channel before switching.
174 + */
175 + if (rt2x00dev->ops->lib->update_survey &&
176 + (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
177 + rt2x00dev->ops->lib->update_survey(rt2x00dev);
178 + }
179 +
180 + /*
181 * Some configuration parameters (e.g. channel and antenna values) can
182 * only be set when the radio is enabled, but do require the RX to
183 * be off. During this period we should keep link tuning enabled,