aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
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
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')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c52
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c10
3 files changed, 60 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 59ce7ec5b224..4169d2b3f71e 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -695,5 +695,8 @@ void ath9k_wiphy_work(struct work_struct *work);
695bool ath9k_all_wiphys_idle(struct ath_softc *sc); 695bool ath9k_all_wiphys_idle(struct ath_softc *sc);
696void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle); 696void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle);
697 697
698void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue);
699void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
700
698int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); 701int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
699#endif /* ATH9K_H */ 702#endif /* ATH9K_H */
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index 69a871ba051f..0a36b572294c 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}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index fc06768e8231..86b54ddd01cb 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -915,9 +915,10 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
915struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) 915struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
916{ 916{
917 struct ath_txq *txq = NULL; 917 struct ath_txq *txq = NULL;
918 u16 skb_queue = skb_get_queue_mapping(skb);
918 int qnum; 919 int qnum;
919 920
920 qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); 921 qnum = ath_get_hal_qnum(skb_queue, sc);
921 txq = &sc->tx.txq[qnum]; 922 txq = &sc->tx.txq[qnum];
922 923
923 spin_lock_bh(&txq->axq_lock); 924 spin_lock_bh(&txq->axq_lock);
@@ -926,7 +927,7 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
926 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT, 927 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
927 "TX queue: %d is full, depth: %d\n", 928 "TX queue: %d is full, depth: %d\n",
928 qnum, txq->axq_depth); 929 qnum, txq->axq_depth);
929 ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); 930 ath_mac80211_stop_queue(sc, skb_queue);
930 txq->stopped = 1; 931 txq->stopped = 1;
931 spin_unlock_bh(&txq->axq_lock); 932 spin_unlock_bh(&txq->axq_lock);
932 return NULL; 933 return NULL;
@@ -1705,8 +1706,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1705 * on the queue */ 1706 * on the queue */
1706 spin_lock_bh(&txq->axq_lock); 1707 spin_lock_bh(&txq->axq_lock);
1707 if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) { 1708 if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
1708 ieee80211_stop_queue(sc->hw, 1709 ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
1709 skb_get_queue_mapping(skb));
1710 txq->stopped = 1; 1710 txq->stopped = 1;
1711 } 1711 }
1712 spin_unlock_bh(&txq->axq_lock); 1712 spin_unlock_bh(&txq->axq_lock);
@@ -1946,7 +1946,7 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
1946 sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) { 1946 sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
1947 qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); 1947 qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
1948 if (qnum != -1) { 1948 if (qnum != -1) {
1949 ieee80211_wake_queue(sc->hw, qnum); 1949 ath_mac80211_start_queue(sc, qnum);
1950 txq->stopped = 0; 1950 txq->stopped = 0;
1951 } 1951 }
1952 } 1952 }