diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2009-03-03 19:23:39 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-05 14:39:48 -0500 |
commit | f98c3bd24161e9aaa73b9cd4dc6b1742c085ac17 (patch) | |
tree | 82a34790535b773f8d2d6b59a715385dc40b3ef9 /drivers/net/wireless/ath9k/virtual.c | |
parent | 8089cc47ed45df8f5a44f92f53140e6fd0958409 (diff) |
ath9k: Add a simple virtual wiphy scheduler
This is a very simple scheduler that goes through the wiphys and
schedules one at a time every N milliseconds (current default value:
500 ms). This is enough for initial testing, but there are number of
areas where a more complex scheduler can improve operations greatly.
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/virtual.c')
-rw-r--r-- | drivers/net/wireless/ath9k/virtual.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath9k/virtual.c b/drivers/net/wireless/ath9k/virtual.c index 2b545319408..1ff429b027d 100644 --- a/drivers/net/wireless/ath9k/virtual.c +++ b/drivers/net/wireless/ath9k/virtual.c @@ -154,6 +154,11 @@ int ath9k_wiphy_add(struct ath_softc *sc) error = ieee80211_register_hw(hw); + if (error == 0) { + /* Make sure wiphy scheduler is started (if enabled) */ + ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); + } + return error; } @@ -596,3 +601,62 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, } spin_unlock_bh(&sc->wiphy_lock); } + +void ath9k_wiphy_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + wiphy_work.work); + struct ath_wiphy *aphy = NULL; + bool first = true; + + spin_lock_bh(&sc->wiphy_lock); + + if (sc->wiphy_scheduler_int == 0) { + /* wiphy scheduler is disabled */ + spin_unlock_bh(&sc->wiphy_lock); + return; + } + +try_again: + sc->wiphy_scheduler_index++; + while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) { + aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1]; + if (aphy && aphy->state != ATH_WIPHY_INACTIVE) + break; + + sc->wiphy_scheduler_index++; + aphy = NULL; + } + if (aphy == NULL) { + sc->wiphy_scheduler_index = 0; + if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) { + if (first) { + first = false; + goto try_again; + } + /* No wiphy is ready to be scheduled */ + } else + aphy = sc->pri_wiphy; + } + + spin_unlock_bh(&sc->wiphy_lock); + + if (aphy && + aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN && + ath9k_wiphy_select(aphy)) { + printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy " + "change\n"); + } + + queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, + sc->wiphy_scheduler_int); +} + +void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) +{ + cancel_delayed_work_sync(&sc->wiphy_work); + sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); + if (sc->wiphy_scheduler_int) + queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, + sc->wiphy_scheduler_int); +} |