aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00config.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00config.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c141
1 files changed, 101 insertions, 40 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 953dc4f2c6af..b704e5b183d0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -60,15 +60,15 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
60 * Note that when NULL is passed as address we will send 60 * Note that when NULL is passed as address we will send
61 * 00:00:00:00:00 to the device to clear the address. 61 * 00:00:00:00:00 to the device to clear the address.
62 * This will prevent the device being confused when it wants 62 * This will prevent the device being confused when it wants
63 * to ACK frames or consideres itself associated. 63 * to ACK frames or considers itself associated.
64 */ 64 */
65 memset(&conf.mac, 0, sizeof(conf.mac)); 65 memset(conf.mac, 0, sizeof(conf.mac));
66 if (mac) 66 if (mac)
67 memcpy(&conf.mac, mac, ETH_ALEN); 67 memcpy(conf.mac, mac, ETH_ALEN);
68 68
69 memset(&conf.bssid, 0, sizeof(conf.bssid)); 69 memset(conf.bssid, 0, sizeof(conf.bssid));
70 if (bssid) 70 if (bssid)
71 memcpy(&conf.bssid, bssid, ETH_ALEN); 71 memcpy(conf.bssid, bssid, ETH_ALEN);
72 72
73 flags |= CONFIG_UPDATE_TYPE; 73 flags |= CONFIG_UPDATE_TYPE;
74 if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) 74 if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
@@ -81,7 +81,8 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
81 81
82void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, 82void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
83 struct rt2x00_intf *intf, 83 struct rt2x00_intf *intf,
84 struct ieee80211_bss_conf *bss_conf) 84 struct ieee80211_bss_conf *bss_conf,
85 u32 changed)
85{ 86{
86 struct rt2x00lib_erp erp; 87 struct rt2x00lib_erp erp;
87 88
@@ -99,19 +100,17 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
99 erp.basic_rates = bss_conf->basic_rates; 100 erp.basic_rates = bss_conf->basic_rates;
100 erp.beacon_int = bss_conf->beacon_int; 101 erp.beacon_int = bss_conf->beacon_int;
101 102
103 /* Update the AID, this is needed for dynamic PS support */
104 rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
105 rt2x00dev->last_beacon = bss_conf->timestamp;
106
102 /* Update global beacon interval time, this is needed for PS support */ 107 /* Update global beacon interval time, this is needed for PS support */
103 rt2x00dev->beacon_int = bss_conf->beacon_int; 108 rt2x00dev->beacon_int = bss_conf->beacon_int;
104 109
105 rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); 110 if (changed & BSS_CHANGED_HT)
106} 111 erp.ht_opmode = bss_conf->ht_operation_mode;
107 112
108static inline 113 rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
109enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
110 enum antenna default_ant)
111{
112 if (current_ant != ANTENNA_SW_DIVERSITY)
113 return current_ant;
114 return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B;
115} 114}
116 115
117void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, 116void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
@@ -122,35 +121,43 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
122 struct antenna_setup *active = &rt2x00dev->link.ant.active; 121 struct antenna_setup *active = &rt2x00dev->link.ant.active;
123 122
124 /* 123 /*
125 * Failsafe: Make sure we are not sending the 124 * When the caller tries to send the SW diversity,
126 * ANTENNA_SW_DIVERSITY state to the driver. 125 * we must update the ANTENNA_RX_DIVERSITY flag to
127 * If that happens, fallback to hardware defaults, 126 * enable the antenna diversity in the link tuner.
128 * or our own default. 127 *
129 * If diversity handling is active for a particular antenna, 128 * Secondly, we must guarentee we never send the
130 * we shouldn't overwrite that antenna. 129 * software antenna diversity command to the driver.
131 * The calls to rt2x00lib_config_antenna_check()
132 * might have caused that we restore back to the already
133 * active setting. If that has happened we can quit.
134 */ 130 */
135 if (!(ant->flags & ANTENNA_RX_DIVERSITY)) 131 if (!(ant->flags & ANTENNA_RX_DIVERSITY)) {
136 config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); 132 if (config.rx == ANTENNA_SW_DIVERSITY) {
137 else 133 ant->flags |= ANTENNA_RX_DIVERSITY;
134
135 if (def->rx == ANTENNA_SW_DIVERSITY)
136 config.rx = ANTENNA_B;
137 else
138 config.rx = def->rx;
139 }
140 } else if (config.rx == ANTENNA_SW_DIVERSITY)
138 config.rx = active->rx; 141 config.rx = active->rx;
139 142
140 if (!(ant->flags & ANTENNA_TX_DIVERSITY)) 143 if (!(ant->flags & ANTENNA_TX_DIVERSITY)) {
141 config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx); 144 if (config.tx == ANTENNA_SW_DIVERSITY) {
142 else 145 ant->flags |= ANTENNA_TX_DIVERSITY;
143 config.tx = active->tx;
144 146
145 if (config.rx == active->rx && config.tx == active->tx) 147 if (def->tx == ANTENNA_SW_DIVERSITY)
146 return; 148 config.tx = ANTENNA_B;
149 else
150 config.tx = def->tx;
151 }
152 } else if (config.tx == ANTENNA_SW_DIVERSITY)
153 config.tx = active->tx;
147 154
148 /* 155 /*
149 * Antenna setup changes require the RX to be disabled, 156 * Antenna setup changes require the RX to be disabled,
150 * else the changes will be ignored by the device. 157 * else the changes will be ignored by the device.
151 */ 158 */
152 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 159 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
153 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); 160 rt2x00queue_stop_queue(rt2x00dev->rx);
154 161
155 /* 162 /*
156 * Write new antenna setup to device and reset the link tuner. 163 * Write new antenna setup to device and reset the link tuner.
@@ -164,7 +171,35 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
164 memcpy(active, &config, sizeof(config)); 171 memcpy(active, &config, sizeof(config));
165 172
166 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 173 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
167 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); 174 rt2x00queue_start_queue(rt2x00dev->rx);
175}
176
177static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
178 struct ieee80211_conf *conf)
179{
180 struct hw_mode_spec *spec = &rt2x00dev->spec;
181 int center_channel;
182 u16 i;
183
184 /*
185 * Initialize center channel to current channel.
186 */
187 center_channel = spec->channels[conf->channel->hw_value].channel;
188
189 /*
190 * Adjust center channel to HT40+ and HT40- operation.
191 */
192 if (conf_is_ht40_plus(conf))
193 center_channel += 2;
194 else if (conf_is_ht40_minus(conf))
195 center_channel -= (center_channel == 14) ? 1 : 2;
196
197 for (i = 0; i < spec->num_channels; i++)
198 if (spec->channels[i].channel == center_channel)
199 return i;
200
201 WARN_ON(1);
202 return conf->channel->hw_value;
168} 203}
169 204
170void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, 205void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
@@ -173,6 +208,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
173{ 208{
174 struct rt2x00lib_conf libconf; 209 struct rt2x00lib_conf libconf;
175 u16 hw_value; 210 u16 hw_value;
211 u16 autowake_timeout;
212 u16 beacon_int;
213 u16 beacon_diff;
176 214
177 memset(&libconf, 0, sizeof(libconf)); 215 memset(&libconf, 0, sizeof(libconf));
178 216
@@ -180,10 +218,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
180 218
181 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { 219 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
182 if (conf_is_ht40(conf)) { 220 if (conf_is_ht40(conf)) {
183 __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); 221 set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
184 hw_value = rt2x00ht_center_channel(rt2x00dev, conf); 222 hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
185 } else { 223 } else {
186 __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); 224 clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
187 hw_value = conf->channel->hw_value; 225 hw_value = conf->channel->hw_value;
188 } 226 }
189 227
@@ -196,6 +234,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
196 sizeof(libconf.channel)); 234 sizeof(libconf.channel));
197 } 235 }
198 236
237 if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
238 (ieee80211_flags & IEEE80211_CONF_CHANGE_PS))
239 cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
240
199 /* 241 /*
200 * Start configuration. 242 * Start configuration.
201 */ 243 */
@@ -208,11 +250,30 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
208 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) 250 if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
209 rt2x00link_reset_tuner(rt2x00dev, false); 251 rt2x00link_reset_tuner(rt2x00dev, false);
210 252
253 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
254 test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
255 (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) &&
256 (conf->flags & IEEE80211_CONF_PS)) {
257 beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon;
258 beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int);
259
260 if (beacon_diff > beacon_int)
261 beacon_diff = 0;
262
263 autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff;
264 queue_delayed_work(rt2x00dev->workqueue,
265 &rt2x00dev->autowakeup_work,
266 autowake_timeout - 15);
267 }
268
269 if (conf->flags & IEEE80211_CONF_PS)
270 set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
271 else
272 clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
273
211 rt2x00dev->curr_band = conf->channel->band; 274 rt2x00dev->curr_band = conf->channel->band;
275 rt2x00dev->curr_freq = conf->channel->center_freq;
212 rt2x00dev->tx_power = conf->power_level; 276 rt2x00dev->tx_power = conf->power_level;
213 rt2x00dev->short_retry = conf->short_frame_max_tx_count; 277 rt2x00dev->short_retry = conf->short_frame_max_tx_count;
214 rt2x00dev->long_retry = conf->long_frame_max_tx_count; 278 rt2x00dev->long_retry = conf->long_frame_max_tx_count;
215
216 rt2x00dev->rx_status.band = conf->channel->band;
217 rt2x00dev->rx_status.freq = conf->channel->center_freq;
218} 279}