Skip to content

Commit

Permalink
ath9k: disable radio when all devices are marked idle
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Luis R. Rodriguez authored and John W. Linville committed Jul 24, 2009
1 parent 709ade9 commit 6483917
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
struct ath_wiphy *selected);
bool ath9k_wiphy_scanning(struct ath_softc *sc);
void ath9k_wiphy_work(struct work_struct *work);
bool ath9k_all_wiphys_idle(struct ath_softc *sc);

void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val);
unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset);
Expand Down
24 changes: 24 additions & 0 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2260,9 +2260,28 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
struct ath_softc *sc = aphy->sc;
struct ieee80211_conf *conf = &hw->conf;
struct ath_hw *ah = sc->sc_ah;
bool all_wiphys_idle = false, disable_radio = false;

mutex_lock(&sc->mutex);

/* Leave this as the first check */
if (changed & IEEE80211_CONF_CHANGE_IDLE) {

spin_lock_bh(&sc->wiphy_lock);
all_wiphys_idle = ath9k_all_wiphys_idle(sc);
spin_unlock_bh(&sc->wiphy_lock);

if (conf->flags & IEEE80211_CONF_IDLE){
if (all_wiphys_idle)
disable_radio = true;
}
else if (all_wiphys_idle) {
ath_radio_enable(sc);
DPRINTF(sc, ATH_DBG_CONFIG,
"not-idle: enabling radio\n");
}
}

if (changed & IEEE80211_CONF_CHANGE_PS) {
if (conf->flags & IEEE80211_CONF_PS) {
if (!(ah->caps.hw_caps &
Expand Down Expand Up @@ -2330,6 +2349,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_POWER)
sc->config.txpowlimit = 2 * conf->power_level;

if (disable_radio) {
DPRINTF(sc, ATH_DBG_CONFIG, "idle: disabling radio\n");
ath_radio_disable(sc);
}

mutex_unlock(&sc->mutex);

return 0;
Expand Down
17 changes: 17 additions & 0 deletions drivers/net/wireless/ath/ath9k/virtual.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,3 +660,20 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work,
sc->wiphy_scheduler_int);
}

/* caller must hold wiphy_lock */
bool ath9k_all_wiphys_idle(struct ath_softc *sc)
{
unsigned int i;
if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) {
return false;
}
for (i = 0; i < sc->num_sec_wiphy; i++) {
struct ath_wiphy *aphy = sc->sec_wiphy[i];
if (!aphy)
continue;
if (aphy->state != ATH_WIPHY_INACTIVE)
return false;
}
return true;
}

0 comments on commit 6483917

Please sign in to comment.