diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2009-07-14 20:22:53 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:19 -0400 |
commit | 64839170be296e6348fbaf83fd103711978669b9 (patch) | |
tree | efc597e35a98417fd6910eacf92a36b8d206e2ae /drivers | |
parent | 709ade9eb8ef06e03526115408e2fc93a9feabbd (diff) |
ath9k: disable radio when all devices are marked idle
This uses the new configuration changes indicated up by
mac80211 when all interfaces are marked idle. We need to do
a little more work as we have our own set of virtual
wiphys within ath9k.
Only when all virtual wiphys are inactive do we allow an idle
state change for a wiphy to trigger disabling the radio.
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/virtual.c | 17 |
3 files changed, 42 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 157681241733..751885a5df47 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -691,6 +691,7 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | |||
691 | struct ath_wiphy *selected); | 691 | struct ath_wiphy *selected); |
692 | bool ath9k_wiphy_scanning(struct ath_softc *sc); | 692 | bool ath9k_wiphy_scanning(struct ath_softc *sc); |
693 | void ath9k_wiphy_work(struct work_struct *work); | 693 | void ath9k_wiphy_work(struct work_struct *work); |
694 | bool ath9k_all_wiphys_idle(struct ath_softc *sc); | ||
694 | 695 | ||
695 | void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); | 696 | void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); |
696 | unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); | 697 | unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d14f8c9cef68..254e78786eee 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -2260,9 +2260,28 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2260 | struct ath_softc *sc = aphy->sc; | 2260 | struct ath_softc *sc = aphy->sc; |
2261 | struct ieee80211_conf *conf = &hw->conf; | 2261 | struct ieee80211_conf *conf = &hw->conf; |
2262 | struct ath_hw *ah = sc->sc_ah; | 2262 | struct ath_hw *ah = sc->sc_ah; |
2263 | bool all_wiphys_idle = false, disable_radio = false; | ||
2263 | 2264 | ||
2264 | mutex_lock(&sc->mutex); | 2265 | mutex_lock(&sc->mutex); |
2265 | 2266 | ||
2267 | /* Leave this as the first check */ | ||
2268 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | ||
2269 | |||
2270 | spin_lock_bh(&sc->wiphy_lock); | ||
2271 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); | ||
2272 | spin_unlock_bh(&sc->wiphy_lock); | ||
2273 | |||
2274 | if (conf->flags & IEEE80211_CONF_IDLE){ | ||
2275 | if (all_wiphys_idle) | ||
2276 | disable_radio = true; | ||
2277 | } | ||
2278 | else if (all_wiphys_idle) { | ||
2279 | ath_radio_enable(sc); | ||
2280 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
2281 | "not-idle: enabling radio\n"); | ||
2282 | } | ||
2283 | } | ||
2284 | |||
2266 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 2285 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
2267 | if (conf->flags & IEEE80211_CONF_PS) { | 2286 | if (conf->flags & IEEE80211_CONF_PS) { |
2268 | if (!(ah->caps.hw_caps & | 2287 | if (!(ah->caps.hw_caps & |
@@ -2330,6 +2349,11 @@ skip_chan_change: | |||
2330 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2349 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
2331 | sc->config.txpowlimit = 2 * conf->power_level; | 2350 | sc->config.txpowlimit = 2 * conf->power_level; |
2332 | 2351 | ||
2352 | if (disable_radio) { | ||
2353 | DPRINTF(sc, ATH_DBG_CONFIG, "idle: disabling radio\n"); | ||
2354 | ath_radio_disable(sc); | ||
2355 | } | ||
2356 | |||
2333 | mutex_unlock(&sc->mutex); | 2357 | mutex_unlock(&sc->mutex); |
2334 | 2358 | ||
2335 | return 0; | 2359 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 1ff429b027d7..e1d419e02b4a 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -660,3 +660,20 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) | |||
660 | queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, | 660 | queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, |
661 | sc->wiphy_scheduler_int); | 661 | sc->wiphy_scheduler_int); |
662 | } | 662 | } |
663 | |||
664 | /* caller must hold wiphy_lock */ | ||
665 | bool ath9k_all_wiphys_idle(struct ath_softc *sc) | ||
666 | { | ||
667 | unsigned int i; | ||
668 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { | ||
669 | return false; | ||
670 | } | ||
671 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
672 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
673 | if (!aphy) | ||
674 | continue; | ||
675 | if (aphy->state != ATH_WIPHY_INACTIVE) | ||
676 | return false; | ||
677 | } | ||
678 | return true; | ||
679 | } | ||