diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2009-03-03 12:23:32 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-05 14:39:46 -0500 |
commit | 0e2dedf971f3feefd4d3d3d8cb5c57b1757f1101 (patch) | |
tree | 8ae3400d17331c000ac204ab85a970434f5e5233 /drivers/net/wireless/ath9k/main.c | |
parent | f0ed85c6c7960b26666db013e02e748b56eef98a (diff) |
ath9k: Add routines for switching between active virtual wiphys
ath9k_wiphy_select() can be used to select a virtual wiphy to be
activated. Other virtual wiphys will be paused and once that is done,
the operational channel is changed and the wiphys that are on the
selected channel will be unpaused.
Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 7e44013ba6e7..44959010c547 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -236,11 +236,11 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) | |||
236 | * by reseting the chip. To accomplish this we must first cleanup any pending | 236 | * by reseting the chip. To accomplish this we must first cleanup any pending |
237 | * DMA, then restart stuff. | 237 | * DMA, then restart stuff. |
238 | */ | 238 | */ |
239 | static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) | 239 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, |
240 | struct ath9k_channel *hchan) | ||
240 | { | 241 | { |
241 | struct ath_hw *ah = sc->sc_ah; | 242 | struct ath_hw *ah = sc->sc_ah; |
242 | bool fastcc = true, stopped; | 243 | bool fastcc = true, stopped; |
243 | struct ieee80211_hw *hw = sc->hw; | ||
244 | struct ieee80211_channel *channel = hw->conf.channel; | 244 | struct ieee80211_channel *channel = hw->conf.channel; |
245 | int r; | 245 | int r; |
246 | 246 | ||
@@ -414,7 +414,7 @@ set_timer: | |||
414 | * the chainmask configuration, for bt coexistence, use | 414 | * the chainmask configuration, for bt coexistence, use |
415 | * the chainmask configuration even in legacy mode. | 415 | * the chainmask configuration even in legacy mode. |
416 | */ | 416 | */ |
417 | static void ath_update_chainmask(struct ath_softc *sc, int is_ht) | 417 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) |
418 | { | 418 | { |
419 | sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; | 419 | sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; |
420 | if (is_ht || | 420 | if (is_ht || |
@@ -1324,6 +1324,7 @@ void ath_detach(struct ath_softc *sc) | |||
1324 | ath_deinit_rfkill(sc); | 1324 | ath_deinit_rfkill(sc); |
1325 | #endif | 1325 | #endif |
1326 | ath_deinit_leds(sc); | 1326 | ath_deinit_leds(sc); |
1327 | cancel_work_sync(&sc->chan_work); | ||
1327 | 1328 | ||
1328 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 1329 | for (i = 0; i < sc->num_sec_wiphy; i++) { |
1329 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 1330 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
@@ -1669,6 +1670,8 @@ int ath_attach(u16 devid, struct ath_softc *sc) | |||
1669 | ath9k_reg_apply_radar_flags(hw->wiphy); | 1670 | ath9k_reg_apply_radar_flags(hw->wiphy); |
1670 | ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT); | 1671 | ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT); |
1671 | 1672 | ||
1673 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | ||
1674 | |||
1672 | error = ieee80211_register_hw(hw); | 1675 | error = ieee80211_register_hw(hw); |
1673 | 1676 | ||
1674 | if (!ath9k_is_world_regd(sc->sc_ah)) { | 1677 | if (!ath9k_is_world_regd(sc->sc_ah)) { |
@@ -1917,10 +1920,9 @@ int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) | |||
1917 | 1920 | ||
1918 | /* XXX: Remove me once we don't depend on ath9k_channel for all | 1921 | /* XXX: Remove me once we don't depend on ath9k_channel for all |
1919 | * this redundant data */ | 1922 | * this redundant data */ |
1920 | static void ath9k_update_ichannel(struct ath_softc *sc, | 1923 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, |
1921 | struct ath9k_channel *ichan) | 1924 | struct ath9k_channel *ichan) |
1922 | { | 1925 | { |
1923 | struct ieee80211_hw *hw = sc->hw; | ||
1924 | struct ieee80211_channel *chan = hw->conf.channel; | 1926 | struct ieee80211_channel *chan = hw->conf.channel; |
1925 | struct ieee80211_conf *conf = &hw->conf; | 1927 | struct ieee80211_conf *conf = &hw->conf; |
1926 | 1928 | ||
@@ -1967,8 +1969,9 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1967 | 1969 | ||
1968 | pos = curchan->hw_value; | 1970 | pos = curchan->hw_value; |
1969 | 1971 | ||
1972 | sc->chan_idx = pos; | ||
1970 | init_channel = &sc->sc_ah->channels[pos]; | 1973 | init_channel = &sc->sc_ah->channels[pos]; |
1971 | ath9k_update_ichannel(sc, init_channel); | 1974 | ath9k_update_ichannel(sc, hw, init_channel); |
1972 | 1975 | ||
1973 | /* Reset SERDES registers */ | 1976 | /* Reset SERDES registers */ |
1974 | ath9k_hw_configpcipowersave(sc->sc_ah, 0); | 1977 | ath9k_hw_configpcipowersave(sc->sc_ah, 0); |
@@ -2307,15 +2310,21 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2307 | struct ieee80211_channel *curchan = hw->conf.channel; | 2310 | struct ieee80211_channel *curchan = hw->conf.channel; |
2308 | int pos = curchan->hw_value; | 2311 | int pos = curchan->hw_value; |
2309 | 2312 | ||
2313 | aphy->chan_idx = pos; | ||
2314 | aphy->chan_is_ht = conf_is_ht(conf); | ||
2315 | |||
2316 | /* TODO: do not change operation channel immediately if there | ||
2317 | * are other virtual wiphys that use another channel */ | ||
2318 | |||
2310 | DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | 2319 | DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", |
2311 | curchan->center_freq); | 2320 | curchan->center_freq); |
2312 | 2321 | ||
2313 | /* XXX: remove me eventualy */ | 2322 | /* XXX: remove me eventualy */ |
2314 | ath9k_update_ichannel(sc, &sc->sc_ah->channels[pos]); | 2323 | ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); |
2315 | 2324 | ||
2316 | ath_update_chainmask(sc, conf_is_ht(conf)); | 2325 | ath_update_chainmask(sc, conf_is_ht(conf)); |
2317 | 2326 | ||
2318 | if (ath_set_channel(sc, &sc->sc_ah->channels[pos]) < 0) { | 2327 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { |
2319 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); | 2328 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); |
2320 | mutex_unlock(&sc->mutex); | 2329 | mutex_unlock(&sc->mutex); |
2321 | return -EINVAL; | 2330 | return -EINVAL; |