diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00mac.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index abbd857ec759..235e037e6509 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -273,16 +273,24 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
273 | mutex_init(&intf->beacon_skb_mutex); | 273 | mutex_init(&intf->beacon_skb_mutex); |
274 | intf->beacon = entry; | 274 | intf->beacon = entry; |
275 | 275 | ||
276 | if (vif->type == NL80211_IFTYPE_AP) | ||
277 | memcpy(&intf->bssid, vif->addr, ETH_ALEN); | ||
278 | memcpy(&intf->mac, vif->addr, ETH_ALEN); | ||
279 | |||
280 | /* | 276 | /* |
281 | * The MAC adddress must be configured after the device | 277 | * The MAC adddress must be configured after the device |
282 | * has been initialized. Otherwise the device can reset | 278 | * has been initialized. Otherwise the device can reset |
283 | * the MAC registers. | 279 | * the MAC registers. |
280 | * The BSSID address must only be configured in AP mode, | ||
281 | * however we should not send an empty BSSID address for | ||
282 | * STA interfaces at this time, since this can cause | ||
283 | * invalid behavior in the device. | ||
284 | */ | 284 | */ |
285 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); | 285 | memcpy(&intf->mac, vif->addr, ETH_ALEN); |
286 | if (vif->type == NL80211_IFTYPE_AP) { | ||
287 | memcpy(&intf->bssid, vif->addr, ETH_ALEN); | ||
288 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, | ||
289 | intf->mac, intf->bssid); | ||
290 | } else { | ||
291 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, | ||
292 | intf->mac, NULL); | ||
293 | } | ||
286 | 294 | ||
287 | /* | 295 | /* |
288 | * Some filters depend on the current working mode. We can force | 296 | * Some filters depend on the current working mode. We can force |
@@ -346,9 +354,11 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) | |||
346 | /* | 354 | /* |
347 | * Some configuration parameters (e.g. channel and antenna values) can | 355 | * Some configuration parameters (e.g. channel and antenna values) can |
348 | * only be set when the radio is enabled, but do require the RX to | 356 | * only be set when the radio is enabled, but do require the RX to |
349 | * be off. | 357 | * be off. During this period we should keep link tuning enabled, |
358 | * if for any reason the link tuner must be reset, this will be | ||
359 | * handled by rt2x00lib_config(). | ||
350 | */ | 360 | */ |
351 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); | 361 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); |
352 | 362 | ||
353 | /* | 363 | /* |
354 | * When we've just turned on the radio, we want to reprogram | 364 | * When we've just turned on the radio, we want to reprogram |
@@ -366,7 +376,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) | |||
366 | rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); | 376 | rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); |
367 | 377 | ||
368 | /* Turn RX back on */ | 378 | /* Turn RX back on */ |
369 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); | 379 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); |
370 | 380 | ||
371 | return 0; | 381 | return 0; |
372 | } | 382 | } |
@@ -430,12 +440,36 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
430 | } | 440 | } |
431 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); | 441 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); |
432 | 442 | ||
443 | static void rt2x00mac_set_tim_iter(void *data, u8 *mac, | ||
444 | struct ieee80211_vif *vif) | ||
445 | { | ||
446 | struct rt2x00_intf *intf = vif_to_intf(vif); | ||
447 | |||
448 | if (vif->type != NL80211_IFTYPE_AP && | ||
449 | vif->type != NL80211_IFTYPE_ADHOC && | ||
450 | vif->type != NL80211_IFTYPE_MESH_POINT && | ||
451 | vif->type != NL80211_IFTYPE_WDS) | ||
452 | return; | ||
453 | |||
454 | spin_lock(&intf->lock); | ||
455 | intf->delayed_flags |= DELAYED_UPDATE_BEACON; | ||
456 | spin_unlock(&intf->lock); | ||
457 | } | ||
458 | |||
433 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 459 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
434 | bool set) | 460 | bool set) |
435 | { | 461 | { |
436 | struct rt2x00_dev *rt2x00dev = hw->priv; | 462 | struct rt2x00_dev *rt2x00dev = hw->priv; |
437 | 463 | ||
438 | rt2x00lib_beacondone(rt2x00dev); | 464 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
465 | return 0; | ||
466 | |||
467 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, | ||
468 | rt2x00mac_set_tim_iter, | ||
469 | rt2x00dev); | ||
470 | |||
471 | /* queue work to upodate the beacon template */ | ||
472 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work); | ||
439 | return 0; | 473 | return 0; |
440 | } | 474 | } |
441 | EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); | 475 | EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); |
@@ -539,6 +573,22 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
539 | EXPORT_SYMBOL_GPL(rt2x00mac_set_key); | 573 | EXPORT_SYMBOL_GPL(rt2x00mac_set_key); |
540 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ | 574 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ |
541 | 575 | ||
576 | void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) | ||
577 | { | ||
578 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
579 | __set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); | ||
580 | rt2x00link_stop_tuner(rt2x00dev); | ||
581 | } | ||
582 | EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); | ||
583 | |||
584 | void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw) | ||
585 | { | ||
586 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
587 | __clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); | ||
588 | rt2x00link_start_tuner(rt2x00dev); | ||
589 | } | ||
590 | EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete); | ||
591 | |||
542 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, | 592 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, |
543 | struct ieee80211_low_level_stats *stats) | 593 | struct ieee80211_low_level_stats *stats) |
544 | { | 594 | { |
@@ -562,7 +612,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
562 | { | 612 | { |
563 | struct rt2x00_dev *rt2x00dev = hw->priv; | 613 | struct rt2x00_dev *rt2x00dev = hw->priv; |
564 | struct rt2x00_intf *intf = vif_to_intf(vif); | 614 | struct rt2x00_intf *intf = vif_to_intf(vif); |
565 | int update_bssid = 0; | ||
566 | 615 | ||
567 | /* | 616 | /* |
568 | * mac80211 might be calling this function while we are trying | 617 | * mac80211 might be calling this function while we are trying |
@@ -577,10 +626,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
577 | * conf->bssid can be NULL if coming from the internal | 626 | * conf->bssid can be NULL if coming from the internal |
578 | * beacon update routine. | 627 | * beacon update routine. |
579 | */ | 628 | */ |
580 | if (changes & BSS_CHANGED_BSSID) { | 629 | if (changes & BSS_CHANGED_BSSID) |
581 | update_bssid = 1; | ||
582 | memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); | 630 | memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); |
583 | } | ||
584 | 631 | ||
585 | spin_unlock(&intf->lock); | 632 | spin_unlock(&intf->lock); |
586 | 633 | ||
@@ -592,7 +639,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
592 | */ | 639 | */ |
593 | if (changes & BSS_CHANGED_BSSID) | 640 | if (changes & BSS_CHANGED_BSSID) |
594 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, | 641 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, |
595 | update_bssid ? bss_conf->bssid : NULL); | 642 | bss_conf->bssid); |
596 | 643 | ||
597 | /* | 644 | /* |
598 | * Update the beacon. | 645 | * Update the beacon. |