aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/virtual.c
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-11-02 20:09:12 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-11 17:09:03 -0500
commitf52de03bf9843673cadff8016a609e1628c139e2 (patch)
treee750810d10c44dee9303af41425cc383ff58d16c /drivers/net/wireless/ath/ath9k/virtual.c
parent5008f3727b05b5eb970ce703721aa5897a088e30 (diff)
ath9k: handle low buffer space for virtual wiphys
ath9k virtual wiphys all share the same internal buffer space for TX but they do not share the mac80211 skb queues. When ath9k detects it is running low on buffer space to TX it tells mac80211 to stop sending it skbs its way but it always does this only for the primary wiphy. This means mac80211 won't know its best to avoid sending ath9k more skbs on a separate virtual wiphy. The same issue is present for reliving the skb queue. Since ath9k does not keep track of which virtual wiphy is hammering on TX silence all wiphy's TX when we're low on buffer space. When we're free on buffer space only bother informing the virtual wiphy which is active that we have free buffers. Cc: Jouni.Malinen <Jouni.Malinen@atheros.com> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/virtual.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index 69a871ba051..0a36b572294 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -697,3 +697,55 @@ void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle)
697 wiphy_name(aphy->hw->wiphy), 697 wiphy_name(aphy->hw->wiphy),
698 idle ? "idle" : "not-idle"); 698 idle ? "idle" : "not-idle");
699} 699}
700/* Only bother starting a queue on an active virtual wiphy */
701void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
702{
703 struct ieee80211_hw *hw = sc->pri_wiphy->hw;
704 unsigned int i;
705
706 spin_lock_bh(&sc->wiphy_lock);
707
708 /* Start the primary wiphy */
709 if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) {
710 ieee80211_wake_queue(hw, skb_queue);
711 goto unlock;
712 }
713
714 /* Now start the secondary wiphy queues */
715 for (i = 0; i < sc->num_sec_wiphy; i++) {
716 struct ath_wiphy *aphy = sc->sec_wiphy[i];
717 if (!aphy)
718 continue;
719 if (aphy->state != ATH_WIPHY_ACTIVE)
720 continue;
721
722 hw = aphy->hw;
723 ieee80211_wake_queue(hw, skb_queue);
724 break;
725 }
726
727unlock:
728 spin_unlock_bh(&sc->wiphy_lock);
729}
730
731/* Go ahead and propagate information to all virtual wiphys, it won't hurt */
732void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue)
733{
734 struct ieee80211_hw *hw = sc->pri_wiphy->hw;
735 unsigned int i;
736
737 spin_lock_bh(&sc->wiphy_lock);
738
739 /* Stop the primary wiphy */
740 ieee80211_stop_queue(hw, skb_queue);
741
742 /* Now stop the secondary wiphy queues */
743 for (i = 0; i < sc->num_sec_wiphy; i++) {
744 struct ath_wiphy *aphy = sc->sec_wiphy[i];
745 if (!aphy)
746 continue;
747 hw = aphy->hw;
748 ieee80211_stop_queue(hw, skb_queue);
749 }
750 spin_unlock_bh(&sc->wiphy_lock);
751}