diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2009-03-03 12:23:39 -0500 |
---|---|---|
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 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) | |||
154 | 154 | ||
155 | error = ieee80211_register_hw(hw); | 155 | error = ieee80211_register_hw(hw); |
156 | 156 | ||
157 | if (error == 0) { | ||
158 | /* Make sure wiphy scheduler is started (if enabled) */ | ||
159 | ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); | ||
160 | } | ||
161 | |||
157 | return error; | 162 | return error; |
158 | } | 163 | } |
159 | 164 | ||
@@ -596,3 +601,62 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | |||
596 | } | 601 | } |
597 | spin_unlock_bh(&sc->wiphy_lock); | 602 | spin_unlock_bh(&sc->wiphy_lock); |
598 | } | 603 | } |
604 | |||
605 | void ath9k_wiphy_work(struct work_struct *work) | ||
606 | { | ||
607 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
608 | wiphy_work.work); | ||
609 | struct ath_wiphy *aphy = NULL; | ||
610 | bool first = true; | ||
611 | |||
612 | spin_lock_bh(&sc->wiphy_lock); | ||
613 | |||
614 | if (sc->wiphy_scheduler_int == 0) { | ||
615 | /* wiphy scheduler is disabled */ | ||
616 | spin_unlock_bh(&sc->wiphy_lock); | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | try_again: | ||
621 | sc->wiphy_scheduler_index++; | ||
622 | while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) { | ||
623 | aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1]; | ||
624 | if (aphy && aphy->state != ATH_WIPHY_INACTIVE) | ||
625 | break; | ||
626 | |||
627 | sc->wiphy_scheduler_index++; | ||
628 | aphy = NULL; | ||
629 | } | ||
630 | if (aphy == NULL) { | ||
631 | sc->wiphy_scheduler_index = 0; | ||
632 | if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) { | ||
633 | if (first) { | ||
634 | first = false; | ||
635 | goto try_again; | ||
636 | } | ||
637 | /* No wiphy is ready to be scheduled */ | ||
638 | } else | ||
639 | aphy = sc->pri_wiphy; | ||
640 | } | ||
641 | |||
642 | spin_unlock_bh(&sc->wiphy_lock); | ||
643 | |||
644 | if (aphy && | ||
645 | aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN && | ||
646 | ath9k_wiphy_select(aphy)) { | ||
647 | printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy " | ||
648 | "change\n"); | ||
649 | } | ||
650 | |||
651 | queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, | ||
652 | sc->wiphy_scheduler_int); | ||
653 | } | ||
654 | |||
655 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) | ||
656 | { | ||
657 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
658 | sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); | ||
659 | if (sc->wiphy_scheduler_int) | ||
660 | queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, | ||
661 | sc->wiphy_scheduler_int); | ||
662 | } | ||