aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2010-10-08 15:01:15 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-11 15:04:19 -0400
commit62c58fb4316905cd9c1dbf01967935ed5610b45d (patch)
tree088cea1c12ac3ad53bd7b75275bcbef4666ce3ba
parent92c68a66a8f73c51f062ae8cae958c86a21fea78 (diff)
ath5k: Adjust opmode when interfaces are removed.
Otherwise, if there is an AP and a STATION, and AP is removed, the NIC will not revert back to STATION mode. Reported-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Ben Greear <greearb@candelatech.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index dad726585637..c9732a6ce87f 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -62,6 +62,7 @@
62#include "reg.h" 62#include "reg.h"
63#include "debug.h" 63#include "debug.h"
64#include "ani.h" 64#include "ani.h"
65#include "../debug.h"
65 66
66static int modparam_nohwcrypt; 67static int modparam_nohwcrypt;
67module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); 68module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
@@ -517,12 +518,14 @@ struct ath_vif_iter_data {
517 bool need_set_hw_addr; 518 bool need_set_hw_addr;
518 bool found_active; 519 bool found_active;
519 bool any_assoc; 520 bool any_assoc;
521 enum nl80211_iftype opmode;
520}; 522};
521 523
522static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) 524static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
523{ 525{
524 struct ath_vif_iter_data *iter_data = data; 526 struct ath_vif_iter_data *iter_data = data;
525 int i; 527 int i;
528 struct ath5k_vif *avf = (void *)vif->drv_priv;
526 529
527 if (iter_data->hw_macaddr) 530 if (iter_data->hw_macaddr)
528 for (i = 0; i < ETH_ALEN; i++) 531 for (i = 0; i < ETH_ALEN; i++)
@@ -539,13 +542,34 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
539 iter_data->need_set_hw_addr = false; 542 iter_data->need_set_hw_addr = false;
540 543
541 if (!iter_data->any_assoc) { 544 if (!iter_data->any_assoc) {
542 struct ath5k_vif *avf = (void *)vif->drv_priv;
543 if (avf->assoc) 545 if (avf->assoc)
544 iter_data->any_assoc = true; 546 iter_data->any_assoc = true;
545 } 547 }
548
549 /* Calculate combined mode - when APs are active, operate in AP mode.
550 * Otherwise use the mode of the new interface. This can currently
551 * only deal with combinations of APs and STAs. Only one ad-hoc
552 * interfaces is allowed above.
553 */
554 if (avf->opmode == NL80211_IFTYPE_AP)
555 iter_data->opmode = NL80211_IFTYPE_AP;
556 else
557 if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED)
558 iter_data->opmode = avf->opmode;
546} 559}
547 560
548void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif) 561static void ath_do_set_opmode(struct ath5k_softc *sc)
562{
563 struct ath5k_hw *ah = sc->ah;
564 ath5k_hw_set_opmode(ah, sc->opmode);
565 ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
566 sc->opmode,
567 ath_opmode_to_string(sc->opmode) ?
568 ath_opmode_to_string(sc->opmode) : "UKNOWN");
569}
570
571void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
572 struct ieee80211_vif *vif)
549{ 573{
550 struct ath_common *common = ath5k_hw_common(sc->ah); 574 struct ath_common *common = ath5k_hw_common(sc->ah);
551 struct ath_vif_iter_data iter_data; 575 struct ath_vif_iter_data iter_data;
@@ -558,6 +582,7 @@ void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif)
558 memset(&iter_data.mask, 0xff, ETH_ALEN); 582 memset(&iter_data.mask, 0xff, ETH_ALEN);
559 iter_data.found_active = false; 583 iter_data.found_active = false;
560 iter_data.need_set_hw_addr = true; 584 iter_data.need_set_hw_addr = true;
585 iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED;
561 586
562 if (vif) 587 if (vif)
563 ath_vif_iter(&iter_data, vif->addr, vif); 588 ath_vif_iter(&iter_data, vif->addr, vif);
@@ -567,10 +592,18 @@ void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif)
567 &iter_data); 592 &iter_data);
568 memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN); 593 memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
569 594
595 sc->opmode = iter_data.opmode;
596 if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED)
597 /* Nothing active, default to station mode */
598 sc->opmode = NL80211_IFTYPE_STATION;
599
600 ath_do_set_opmode(sc);
601
570 if (iter_data.need_set_hw_addr && iter_data.found_active) 602 if (iter_data.need_set_hw_addr && iter_data.found_active)
571 ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac); 603 ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
572 604
573 ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); 605 if (ath5k_hw_hasbssidmask(sc->ah))
606 ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
574} 607}
575 608
576static void 609static void
@@ -582,15 +615,9 @@ ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
582 /* configure rx filter */ 615 /* configure rx filter */
583 rfilt = sc->filter_flags; 616 rfilt = sc->filter_flags;
584 ath5k_hw_set_rx_filter(ah, rfilt); 617 ath5k_hw_set_rx_filter(ah, rfilt);
585
586 if (ath5k_hw_hasbssidmask(ah))
587 ath5k_update_bssid_mask(sc, vif);
588
589 /* configure operational mode */
590 ath5k_hw_set_opmode(ah, sc->opmode);
591
592 ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode);
593 ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); 618 ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
619
620 ath5k_update_bssid_mask_and_opmode(sc, vif);
594} 621}
595 622
596static inline int 623static inline int
@@ -2688,7 +2715,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
2688 SET_IEEE80211_PERM_ADDR(hw, mac); 2715 SET_IEEE80211_PERM_ADDR(hw, mac);
2689 memcpy(&sc->lladdr, mac, ETH_ALEN); 2716 memcpy(&sc->lladdr, mac, ETH_ALEN);
2690 /* All MAC address bits matter for ACKs */ 2717 /* All MAC address bits matter for ACKs */
2691 ath5k_update_bssid_mask(sc, NULL); 2718 ath5k_update_bssid_mask_and_opmode(sc, NULL);
2692 2719
2693 regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; 2720 regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
2694 ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); 2721 ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
@@ -2786,7 +2813,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
2786{ 2813{
2787 struct ath5k_softc *sc = hw->priv; 2814 struct ath5k_softc *sc = hw->priv;
2788 int ret; 2815 int ret;
2789 struct ath5k_hw *ah = sc->ah;
2790 struct ath5k_vif *avf = (void *)vif->drv_priv; 2816 struct ath5k_vif *avf = (void *)vif->drv_priv;
2791 2817
2792 mutex_lock(&sc->lock); 2818 mutex_lock(&sc->lock);
@@ -2850,18 +2876,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
2850 sc->num_adhoc_vifs++; 2876 sc->num_adhoc_vifs++;
2851 } 2877 }
2852 2878
2853 /* Set combined mode - when APs are configured, operate in AP mode.
2854 * Otherwise use the mode of the new interface. This can currently
2855 * only deal with combinations of APs and STAs. Only one ad-hoc
2856 * interfaces is allowed above.
2857 */
2858 if (sc->num_ap_vifs)
2859 sc->opmode = NL80211_IFTYPE_AP;
2860 else
2861 sc->opmode = vif->type;
2862
2863 ath5k_hw_set_opmode(ah, sc->opmode);
2864
2865 /* Any MAC address is fine, all others are included through the 2879 /* Any MAC address is fine, all others are included through the
2866 * filter. 2880 * filter.
2867 */ 2881 */
@@ -2905,7 +2919,7 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
2905 else if (avf->opmode == NL80211_IFTYPE_ADHOC) 2919 else if (avf->opmode == NL80211_IFTYPE_ADHOC)
2906 sc->num_adhoc_vifs--; 2920 sc->num_adhoc_vifs--;
2907 2921
2908 ath5k_update_bssid_mask(sc, NULL); 2922 ath5k_update_bssid_mask_and_opmode(sc, NULL);
2909 mutex_unlock(&sc->lock); 2923 mutex_unlock(&sc->lock);
2910} 2924}
2911 2925