From f98c3bd24161e9aaa73b9cd4dc6b1742c085ac17 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Mar 2009 19:23:39 +0200 Subject: 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 Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/virtual.c | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'drivers/net/wireless/ath9k/virtual.c') diff --git a/drivers/net/wireless/ath9k/virtual.c b/drivers/net/wireless/ath9k/virtual.c index 2b545319408d..1ff429b027d7 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); +} -- cgit v1.2.3