aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00mac.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-02-03 09:49:59 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:19:28 -0500
commit6bb40dd13b458beb55f5c60dba1cb28e814bd640 (patch)
tree9b2aaa0de4a4d72a7afc3550b08572083b111c57 /drivers/net/wireless/rt2x00/rt2x00mac.c
parent9404ef34e4747228717d6e22ce3827ed366ccf41 (diff)
rt2x00: Add per-interface structure
Rework the interface handling. Delete the interface structure and replace it with a per-interface structure. This changes the way rt2x00 handles the active interface drastically. Copy ieee80211_bss_conf to the this rt2x00_intf structure during the bss_info_changed() callback function. This will allow us to reference it later, and removes the requirement for the device flag SHORT_PREAMBLE flag which is interface specific. Drivers receive the option to give the maximum number of virtual interfaces the device can handle. Virtual interface support: rt2400pci: 1 sta or 1 ap, * monitor interfaces rt2500pci: 1 sta or 1 ap, * monitor interfaces rt2500usb: 1 sta or 1 ap, * monitor interfaces rt61pci: 1 sta or 4 ap, * monitor interfaces rt73usb: 1 sta or 4 ap, * monitor interfaces At the moment none of the drivers support AP and STA interfaces simultaneously, this is a hardware limitation so future support will be very unlikely. Each interface structure receives its dedicated beacon entry, with this we can easily work with beaconing while multiple master mode interfaces are currently active. The configuration handlers for the MAC, BSSID and type are often called together since they all belong to the interface configuration. Merge the 3 configuration calls and cleanup the API between rt2x00lib and the drivers. While we are cleaning up the interface configuration anyway, we might as well clean up the configuration handler as well. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00mac.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c152
1 files changed, 101 insertions, 51 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index f08c151ee4ba..65a2bcd18aa1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -52,11 +52,11 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
52 skb_put(skb, size); 52 skb_put(skb, size);
53 53
54 if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) 54 if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
55 ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id, 55 ieee80211_ctstoself_get(rt2x00dev->hw, control->vif,
56 frag_skb->data, frag_skb->len, control, 56 frag_skb->data, frag_skb->len, control,
57 (struct ieee80211_cts *)(skb->data)); 57 (struct ieee80211_cts *)(skb->data));
58 else 58 else
59 ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id, 59 ieee80211_rts_get(rt2x00dev->hw, control->vif,
60 frag_skb->data, frag_skb->len, control, 60 frag_skb->data, frag_skb->len, control,
61 (struct ieee80211_rts *)(skb->data)); 61 (struct ieee80211_rts *)(skb->data));
62 62
@@ -162,19 +162,67 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
162 struct ieee80211_if_init_conf *conf) 162 struct ieee80211_if_init_conf *conf)
163{ 163{
164 struct rt2x00_dev *rt2x00dev = hw->priv; 164 struct rt2x00_dev *rt2x00dev = hw->priv;
165 struct interface *intf = &rt2x00dev->interface; 165 struct rt2x00_intf *intf = vif_to_intf(conf->vif);
166 struct data_queue *queue =
167 rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
168 struct queue_entry *entry = NULL;
169 unsigned int i;
166 170
167 /* 171 /*
168 * Don't allow interfaces to be added while 172 * Don't allow interfaces to be added
169 * either the device has disappeared or when 173 * the device has disappeared.
170 * another interface is already present.
171 */ 174 */
172 if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || 175 if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
173 is_interface_present(intf)) 176 !test_bit(DEVICE_STARTED, &rt2x00dev->flags))
177 return -ENODEV;
178
179 /*
180 * When we don't support mixed interfaces (a combination
181 * of sta and ap virtual interfaces) then we can only
182 * add this interface when the rival interface count is 0.
183 */
184 if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) &&
185 ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
186 (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count)))
187 return -ENOBUFS;
188
189 /*
190 * Check if we exceeded the maximum amount of supported interfaces.
191 */
192 if ((conf->type == IEEE80211_IF_TYPE_AP &&
193 rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) ||
194 (conf->type != IEEE80211_IF_TYPE_AP &&
195 rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf))
196 return -ENOBUFS;
197
198 /*
199 * Loop through all beacon queues to find a free
200 * entry. Since there are as much beacon entries
201 * as the maximum interfaces, this search shouldn't
202 * fail.
203 */
204 for (i = 0; i < queue->limit; i++) {
205 entry = &queue->entries[i];
206 if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
207 break;
208 }
209
210 if (unlikely(i == queue->limit))
174 return -ENOBUFS; 211 return -ENOBUFS;
175 212
176 intf->id = conf->vif; 213 /*
177 intf->type = conf->type; 214 * We are now absolutely sure the interface can be created,
215 * increase interface count and start initialization.
216 */
217
218 if (conf->type == IEEE80211_IF_TYPE_AP)
219 rt2x00dev->intf_ap_count++;
220 else
221 rt2x00dev->intf_sta_count++;
222
223 spin_lock_init(&intf->lock);
224 intf->beacon = entry;
225
178 if (conf->type == IEEE80211_IF_TYPE_AP) 226 if (conf->type == IEEE80211_IF_TYPE_AP)
179 memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); 227 memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
180 memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); 228 memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
@@ -184,8 +232,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
184 * has been initialized. Otherwise the device can reset 232 * has been initialized. Otherwise the device can reset
185 * the MAC registers. 233 * the MAC registers.
186 */ 234 */
187 rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); 235 rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
188 rt2x00lib_config_type(rt2x00dev, conf->type);
189 236
190 return 0; 237 return 0;
191} 238}
@@ -195,7 +242,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
195 struct ieee80211_if_init_conf *conf) 242 struct ieee80211_if_init_conf *conf)
196{ 243{
197 struct rt2x00_dev *rt2x00dev = hw->priv; 244 struct rt2x00_dev *rt2x00dev = hw->priv;
198 struct interface *intf = &rt2x00dev->interface; 245 struct rt2x00_intf *intf = vif_to_intf(conf->vif);
199 246
200 /* 247 /*
201 * Don't allow interfaces to be remove while 248 * Don't allow interfaces to be remove while
@@ -203,21 +250,27 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
203 * no interface is present. 250 * no interface is present.
204 */ 251 */
205 if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || 252 if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
206 !is_interface_present(intf)) 253 (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) ||
254 (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count))
207 return; 255 return;
208 256
209 intf->id = NULL; 257 if (conf->type == IEEE80211_IF_TYPE_AP)
210 intf->type = IEEE80211_IF_TYPE_INVALID; 258 rt2x00dev->intf_ap_count--;
211 memset(&intf->bssid, 0x00, ETH_ALEN); 259 else
212 memset(&intf->mac, 0x00, ETH_ALEN); 260 rt2x00dev->intf_sta_count--;
261
262 /*
263 * Release beacon entry so it is available for
264 * new interfaces again.
265 */
266 __clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
213 267
214 /* 268 /*
215 * Make sure the bssid and mac address registers 269 * Make sure the bssid and mac address registers
216 * are cleared to prevent false ACKing of frames. 270 * are cleared to prevent false ACKing of frames.
217 */ 271 */
218 rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); 272 rt2x00lib_config_intf(rt2x00dev, intf,
219 rt2x00lib_config_bssid(rt2x00dev, intf->bssid); 273 IEEE80211_IF_TYPE_INVALID, NULL, NULL);
220 rt2x00lib_config_type(rt2x00dev, intf->type);
221} 274}
222EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); 275EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
223 276
@@ -262,7 +315,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
262 struct ieee80211_if_conf *conf) 315 struct ieee80211_if_conf *conf)
263{ 316{
264 struct rt2x00_dev *rt2x00dev = hw->priv; 317 struct rt2x00_dev *rt2x00dev = hw->priv;
265 struct interface *intf = &rt2x00dev->interface; 318 struct rt2x00_intf *intf = vif_to_intf(vif);
266 int status; 319 int status;
267 320
268 /* 321 /*
@@ -272,12 +325,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
272 if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) 325 if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
273 return 0; 326 return 0;
274 327
275 /* 328 spin_lock(&intf->lock);
276 * If the given type does not match the configured type,
277 * there has been a problem.
278 */
279 if (conf->type != intf->type)
280 return -EINVAL;
281 329
282 /* 330 /*
283 * If the interface does not work in master mode, 331 * If the interface does not work in master mode,
@@ -286,7 +334,9 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
286 */ 334 */
287 if (conf->type != IEEE80211_IF_TYPE_AP) 335 if (conf->type != IEEE80211_IF_TYPE_AP)
288 memcpy(&intf->bssid, conf->bssid, ETH_ALEN); 336 memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
289 rt2x00lib_config_bssid(rt2x00dev, intf->bssid); 337 rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, intf->bssid);
338
339 spin_unlock(&intf->lock);
290 340
291 /* 341 /*
292 * We only need to initialize the beacon when master mode is enabled. 342 * We only need to initialize the beacon when master mode is enabled.
@@ -342,35 +392,35 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
342 u32 changes) 392 u32 changes)
343{ 393{
344 struct rt2x00_dev *rt2x00dev = hw->priv; 394 struct rt2x00_dev *rt2x00dev = hw->priv;
345 int short_preamble; 395 struct rt2x00_intf *intf = vif_to_intf(vif);
346 int ack_timeout;
347 int ack_consume_time;
348 int difs;
349 int preamble;
350 396
351 /* 397 /*
352 * We only support changing preamble mode. 398 * When the association status has changed we must reset the link
399 * tuner counter. This is because some drivers determine if they
400 * should perform link tuning based on the number of seconds
401 * while associated or not associated.
353 */ 402 */
354 if (!(changes & BSS_CHANGED_ERP_PREAMBLE)) 403 if (changes & BSS_CHANGED_ASSOC) {
355 return; 404 rt2x00dev->link.count = 0;
356
357 short_preamble = bss_conf->use_short_preamble;
358 preamble = bss_conf->use_short_preamble ?
359 SHORT_PREAMBLE : PREAMBLE;
360 405
361 difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? 406 if (bss_conf->assoc)
362 SHORT_DIFS : DIFS; 407 rt2x00dev->intf_associated++;
363 ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10); 408 else
364 409 rt2x00dev->intf_associated--;
365 ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10); 410 }
366 411
367 if (short_preamble) 412 /*
368 __set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); 413 * When the preamble mode has changed, we should perform additional
369 else 414 * configuration steps. For all other changes we are already done.
370 __clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); 415 */
416 if (changes & BSS_CHANGED_ERP_PREAMBLE) {
417 rt2x00lib_config_preamble(rt2x00dev, intf,
418 bss_conf->use_short_preamble);
371 419
372 rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble, 420 spin_lock(&intf->lock);
373 ack_timeout, ack_consume_time); 421 memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
422 spin_unlock(&intf->lock);
423 }
374} 424}
375EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); 425EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
376 426