ath9k: clean up tx buffer handling
Felix Fietkau [Mon, 19 Apr 2010 17:57:30 +0000 (19:57 +0200)]
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

drivers/net/wireless/ath/ath9k/xmit.c

index cac178a..fcbb4a8 100644 (file)
@@ -261,19 +261,40 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
        hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
 }
 
-static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
+static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
 {
-       struct ath_buf *tbf;
+       struct ath_buf *bf = NULL;
 
        spin_lock_bh(&sc->tx.txbuflock);
-       if (WARN_ON(list_empty(&sc->tx.txbuf))) {
+
+       if (unlikely(list_empty(&sc->tx.txbuf))) {
                spin_unlock_bh(&sc->tx.txbuflock);
                return NULL;
        }
-       tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
-       list_del(&tbf->list);
+
+       bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+       list_del(&bf->list);
+
        spin_unlock_bh(&sc->tx.txbuflock);
 
+       return bf;
+}
+
+static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf)
+{
+       spin_lock_bh(&sc->tx.txbuflock);
+       list_add_tail(&bf->list, &sc->tx.txbuf);
+       spin_unlock_bh(&sc->tx.txbuflock);
+}
+
+static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
+{
+       struct ath_buf *tbf;
+
+       tbf = ath_tx_get_buffer(sc);
+       if (WARN_ON(!tbf))
+               return NULL;
+
        ATH_TXBUF_RESET(tbf);
 
        tbf->aphy = bf->aphy;
@@ -1081,9 +1102,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
                                list_del(&bf->list);
                                spin_unlock_bh(&txq->axq_lock);
 
-                               spin_lock_bh(&sc->tx.txbuflock);
-                               list_add_tail(&bf->list, &sc->tx.txbuf);
-                               spin_unlock_bh(&sc->tx.txbuflock);
+                               ath_tx_return_buffer(sc, bf);
                                continue;
                        }
                }
@@ -1325,25 +1344,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
        txq->axq_depth++;
 }
 
-static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
-{
-       struct ath_buf *bf = NULL;
-
-       spin_lock_bh(&sc->tx.txbuflock);
-
-       if (unlikely(list_empty(&sc->tx.txbuf))) {
-               spin_unlock_bh(&sc->tx.txbuflock);
-               return NULL;
-       }
-
-       bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
-       list_del(&bf->list);
-
-       spin_unlock_bh(&sc->tx.txbuflock);
-
-       return bf;
-}
-
 static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
                              struct list_head *bf_head,
                              struct ath_tx_control *txctl)
@@ -1825,9 +1825,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
                }
                spin_unlock_bh(&txq->axq_lock);
 
-               spin_lock_bh(&sc->tx.txbuflock);
-               list_add_tail(&bf->list, &sc->tx.txbuf);
-               spin_unlock_bh(&sc->tx.txbuflock);
+               ath_tx_return_buffer(sc, bf);
 
                return r;
        }
@@ -2141,13 +2139,12 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
                txq->axq_depth--;
                txok = !(ts.ts_status & ATH9K_TXERR_MASK);
                txq->axq_tx_inprogress = false;
+               if (bf_held)
+                       list_del(&bf_held->list);
                spin_unlock_bh(&txq->axq_lock);
 
-               if (bf_held) {
-                       spin_lock_bh(&sc->tx.txbuflock);
-                       list_move_tail(&bf_held->list, &sc->tx.txbuf);
-                       spin_unlock_bh(&sc->tx.txbuflock);
-               }
+               if (bf_held)
+                       ath_tx_return_buffer(sc, bf_held);
 
                if (!bf_isampdu(bf)) {
                        /*