diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2009-03-03 12:23:33 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-05 14:39:46 -0500 |
commit | 9580a222b8a371c145d7439c1a289b9e77f8fe31 (patch) | |
tree | 6dd8ba41fe920e029c107bf249b9bb7ff89b03cd /drivers/net/wireless | |
parent | 0e2dedf971f3feefd4d3d3d8cb5c57b1757f1101 (diff) |
ath9k: Make start/stop operations aware of virtual wiphys
Instead of always going through initialization/deinitialization steps,
do this only for the first/last wiphy to not break the other wiphys.
Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath9k/ath9k.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/virtual.c | 19 |
3 files changed, 49 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index bc25075913ad..cb9cb7232489 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h | |||
@@ -627,6 +627,7 @@ struct ath_wiphy { | |||
627 | struct ath_softc *sc; /* shared for all virtual wiphys */ | 627 | struct ath_softc *sc; /* shared for all virtual wiphys */ |
628 | struct ieee80211_hw *hw; | 628 | struct ieee80211_hw *hw; |
629 | enum ath_wiphy_state { | 629 | enum ath_wiphy_state { |
630 | ATH_WIPHY_INACTIVE, | ||
630 | ATH_WIPHY_ACTIVE, | 631 | ATH_WIPHY_ACTIVE, |
631 | ATH_WIPHY_PAUSING, | 632 | ATH_WIPHY_PAUSING, |
632 | ATH_WIPHY_PAUSED, | 633 | ATH_WIPHY_PAUSED, |
@@ -708,5 +709,6 @@ int ath9k_wiphy_pause(struct ath_wiphy *aphy); | |||
708 | int ath9k_wiphy_unpause(struct ath_wiphy *aphy); | 709 | int ath9k_wiphy_unpause(struct ath_wiphy *aphy); |
709 | int ath9k_wiphy_select(struct ath_wiphy *aphy); | 710 | int ath9k_wiphy_select(struct ath_wiphy *aphy); |
710 | void ath9k_wiphy_chan_work(struct work_struct *work); | 711 | void ath9k_wiphy_chan_work(struct work_struct *work); |
712 | bool ath9k_wiphy_started(struct ath_softc *sc); | ||
711 | 713 | ||
712 | #endif /* ATH9K_H */ | 714 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 44959010c547..183fb8e07815 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -1965,6 +1965,27 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1965 | 1965 | ||
1966 | mutex_lock(&sc->mutex); | 1966 | mutex_lock(&sc->mutex); |
1967 | 1967 | ||
1968 | if (ath9k_wiphy_started(sc)) { | ||
1969 | if (sc->chan_idx == curchan->hw_value) { | ||
1970 | /* | ||
1971 | * Already on the operational channel, the new wiphy | ||
1972 | * can be marked active. | ||
1973 | */ | ||
1974 | aphy->state = ATH_WIPHY_ACTIVE; | ||
1975 | ieee80211_wake_queues(hw); | ||
1976 | } else { | ||
1977 | /* | ||
1978 | * Another wiphy is on another channel, start the new | ||
1979 | * wiphy in paused state. | ||
1980 | */ | ||
1981 | aphy->state = ATH_WIPHY_PAUSED; | ||
1982 | ieee80211_stop_queues(hw); | ||
1983 | } | ||
1984 | mutex_unlock(&sc->mutex); | ||
1985 | return 0; | ||
1986 | } | ||
1987 | aphy->state = ATH_WIPHY_ACTIVE; | ||
1988 | |||
1968 | /* setup initial channel */ | 1989 | /* setup initial channel */ |
1969 | 1990 | ||
1970 | pos = curchan->hw_value; | 1991 | pos = curchan->hw_value; |
@@ -2104,6 +2125,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2104 | struct ath_wiphy *aphy = hw->priv; | 2125 | struct ath_wiphy *aphy = hw->priv; |
2105 | struct ath_softc *sc = aphy->sc; | 2126 | struct ath_softc *sc = aphy->sc; |
2106 | 2127 | ||
2128 | aphy->state = ATH_WIPHY_INACTIVE; | ||
2129 | |||
2107 | if (sc->sc_flags & SC_OP_INVALID) { | 2130 | if (sc->sc_flags & SC_OP_INVALID) { |
2108 | DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); | 2131 | DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); |
2109 | return; | 2132 | return; |
@@ -2113,6 +2136,11 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2113 | 2136 | ||
2114 | ieee80211_stop_queues(hw); | 2137 | ieee80211_stop_queues(hw); |
2115 | 2138 | ||
2139 | if (ath9k_wiphy_started(sc)) { | ||
2140 | mutex_unlock(&sc->mutex); | ||
2141 | return; /* another wiphy still in use */ | ||
2142 | } | ||
2143 | |||
2116 | /* make sure h/w will not generate any interrupt | 2144 | /* make sure h/w will not generate any interrupt |
2117 | * before setting the invalid flag. */ | 2145 | * before setting the invalid flag. */ |
2118 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 2146 | ath9k_hw_set_interrupts(sc->sc_ah, 0); |
diff --git a/drivers/net/wireless/ath9k/virtual.c b/drivers/net/wireless/ath9k/virtual.c index 76ffdfa860ed..b66aa24d3186 100644 --- a/drivers/net/wireless/ath9k/virtual.c +++ b/drivers/net/wireless/ath9k/virtual.c | |||
@@ -477,3 +477,22 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy) | |||
477 | 477 | ||
478 | return 0; | 478 | return 0; |
479 | } | 479 | } |
480 | |||
481 | bool ath9k_wiphy_started(struct ath_softc *sc) | ||
482 | { | ||
483 | int i; | ||
484 | spin_lock_bh(&sc->wiphy_lock); | ||
485 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { | ||
486 | spin_unlock_bh(&sc->wiphy_lock); | ||
487 | return true; | ||
488 | } | ||
489 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
490 | if (sc->sec_wiphy[i] && | ||
491 | sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) { | ||
492 | spin_unlock_bh(&sc->wiphy_lock); | ||
493 | return true; | ||
494 | } | ||
495 | } | ||
496 | spin_unlock_bh(&sc->wiphy_lock); | ||
497 | return false; | ||
498 | } | ||