aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-03-03 12:23:33 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-03-05 14:39:46 -0500
commit9580a222b8a371c145d7439c1a289b9e77f8fe31 (patch)
tree6dd8ba41fe920e029c107bf249b9bb7ff89b03cd /drivers
parent0e2dedf971f3feefd4d3d3d8cb5c57b1757f1101 (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')
-rw-r--r--drivers/net/wireless/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath9k/main.c28
-rw-r--r--drivers/net/wireless/ath9k/virtual.c19
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);
708int ath9k_wiphy_unpause(struct ath_wiphy *aphy); 709int ath9k_wiphy_unpause(struct ath_wiphy *aphy);
709int ath9k_wiphy_select(struct ath_wiphy *aphy); 710int ath9k_wiphy_select(struct ath_wiphy *aphy);
710void ath9k_wiphy_chan_work(struct work_struct *work); 711void ath9k_wiphy_chan_work(struct work_struct *work);
712bool 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
481bool 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}