aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Randolf <br1@einfach.org>2010-09-16 22:36:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-09-21 11:05:08 -0400
commit925e0b061300c94912be36eac16f0b44249a1add (patch)
tree45045b4e80a4235d3ad90f185f39a445a727e0ee
parent8a63facc376a7b8bb2b64c0ffbdb0949d1d6c71c (diff)
ath5k: Use four hardware queues
Prepare ath5k for WME by using four hardware queues. The way we set up our queues matches the mac80211 queue priority 1:1, so we don't have to do any mapping for queue numbers. Every queue uses 50 of the total 200 available transmit buffers, so the DMA memory usage does not increase with this patch, but it might be good to fine-tune the number of buffers per queue later (depending on the CPU speed and load, and the speed of the medium access, it might not be big enough). Signed-off-by: Bruno Randolf <br1@einfach.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c47
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h5
2 files changed, 45 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 4a07fb89021e..776f415e8567 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -733,6 +733,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
733 733
734 spin_lock_bh(&txq->lock); 734 spin_lock_bh(&txq->lock);
735 list_add_tail(&bf->list, &txq->q); 735 list_add_tail(&bf->list, &txq->q);
736 txq->txq_len++;
736 if (txq->link == NULL) /* is this first packet? */ 737 if (txq->link == NULL) /* is this first packet? */
737 ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); 738 ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr);
738 else /* no, so only link it */ 739 else /* no, so only link it */
@@ -889,6 +890,7 @@ ath5k_txq_setup(struct ath5k_softc *sc,
889 INIT_LIST_HEAD(&txq->q); 890 INIT_LIST_HEAD(&txq->q);
890 spin_lock_init(&txq->lock); 891 spin_lock_init(&txq->lock);
891 txq->setup = true; 892 txq->setup = true;
893 txq->txq_len = 0;
892 } 894 }
893 return &sc->txqs[qnum]; 895 return &sc->txqs[qnum];
894} 896}
@@ -983,6 +985,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
983 spin_lock_bh(&sc->txbuflock); 985 spin_lock_bh(&sc->txbuflock);
984 list_move_tail(&bf->list, &sc->txbuf); 986 list_move_tail(&bf->list, &sc->txbuf);
985 sc->txbuf_len++; 987 sc->txbuf_len++;
988 txq->txq_len--;
986 spin_unlock_bh(&sc->txbuflock); 989 spin_unlock_bh(&sc->txbuflock);
987 } 990 }
988 txq->link = NULL; 991 txq->link = NULL;
@@ -1479,6 +1482,9 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
1479 goto drop_packet; 1482 goto drop_packet;
1480 } 1483 }
1481 1484
1485 if (txq->txq_len >= ATH5K_TXQ_LEN_MAX)
1486 ieee80211_stop_queue(hw, txq->qnum);
1487
1482 spin_lock_irqsave(&sc->txbuflock, flags); 1488 spin_lock_irqsave(&sc->txbuflock, flags);
1483 if (list_empty(&sc->txbuf)) { 1489 if (list_empty(&sc->txbuf)) {
1484 ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); 1490 ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
@@ -1601,13 +1607,14 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
1601 spin_lock(&sc->txbuflock); 1607 spin_lock(&sc->txbuflock);
1602 list_move_tail(&bf->list, &sc->txbuf); 1608 list_move_tail(&bf->list, &sc->txbuf);
1603 sc->txbuf_len++; 1609 sc->txbuf_len++;
1610 txq->txq_len--;
1604 spin_unlock(&sc->txbuflock); 1611 spin_unlock(&sc->txbuflock);
1605 } 1612 }
1606 if (likely(list_empty(&txq->q))) 1613 if (likely(list_empty(&txq->q)))
1607 txq->link = NULL; 1614 txq->link = NULL;
1608 spin_unlock(&txq->lock); 1615 spin_unlock(&txq->lock);
1609 if (sc->txbuf_len > ATH_TXBUF / 5) 1616 if (txq->txq_len < ATH5K_TXQ_LEN_LOW)
1610 ieee80211_wake_queues(sc->hw); 1617 ieee80211_wake_queue(sc->hw, txq->qnum);
1611} 1618}
1612 1619
1613static void 1620static void
@@ -2391,6 +2398,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
2391 struct ath5k_softc *sc = hw->priv; 2398 struct ath5k_softc *sc = hw->priv;
2392 struct ath5k_hw *ah = sc->ah; 2399 struct ath5k_hw *ah = sc->ah;
2393 struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); 2400 struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
2401 struct ath5k_txq *txq;
2394 u8 mac[ETH_ALEN] = {}; 2402 u8 mac[ETH_ALEN] = {};
2395 int ret; 2403 int ret;
2396 2404
@@ -2456,12 +2464,33 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
2456 goto err_bhal; 2464 goto err_bhal;
2457 } 2465 }
2458 2466
2459 sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); 2467 /* This order matches mac80211's queue priority, so we can
2460 if (IS_ERR(sc->txq)) { 2468 * directly use the mac80211 queue number without any mapping */
2469 txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO);
2470 if (IS_ERR(txq)) {
2471 ATH5K_ERR(sc, "can't setup xmit queue\n");
2472 ret = PTR_ERR(txq);
2473 goto err_queues;
2474 }
2475 txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI);
2476 if (IS_ERR(txq)) {
2461 ATH5K_ERR(sc, "can't setup xmit queue\n"); 2477 ATH5K_ERR(sc, "can't setup xmit queue\n");
2462 ret = PTR_ERR(sc->txq); 2478 ret = PTR_ERR(txq);
2463 goto err_queues; 2479 goto err_queues;
2464 } 2480 }
2481 txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE);
2482 if (IS_ERR(txq)) {
2483 ATH5K_ERR(sc, "can't setup xmit queue\n");
2484 ret = PTR_ERR(txq);
2485 goto err_queues;
2486 }
2487 txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
2488 if (IS_ERR(txq)) {
2489 ATH5K_ERR(sc, "can't setup xmit queue\n");
2490 ret = PTR_ERR(txq);
2491 goto err_queues;
2492 }
2493 hw->queues = 4;
2465 2494
2466 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); 2495 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
2467 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); 2496 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
@@ -2554,8 +2583,14 @@ static int
2554ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 2583ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
2555{ 2584{
2556 struct ath5k_softc *sc = hw->priv; 2585 struct ath5k_softc *sc = hw->priv;
2586 u16 qnum = skb_get_queue_mapping(skb);
2587
2588 if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
2589 dev_kfree_skb_any(skb);
2590 return 0;
2591 }
2557 2592
2558 return ath5k_tx_queue(hw, skb, sc->txq); 2593 return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
2559} 2594}
2560 2595
2561static int ath5k_start(struct ieee80211_hw *hw) 2596static int ath5k_start(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index dc1241f9c4e8..5e2366d3db09 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -60,6 +60,9 @@
60#define ATH_TXBUF 200 /* number of TX buffers */ 60#define ATH_TXBUF 200 /* number of TX buffers */
61#define ATH_BCBUF 1 /* number of beacon buffers */ 61#define ATH_BCBUF 1 /* number of beacon buffers */
62 62
63#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
64#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
65
63struct ath5k_buf { 66struct ath5k_buf {
64 struct list_head list; 67 struct list_head list;
65 struct ath5k_desc *desc; /* virtual addr of desc */ 68 struct ath5k_desc *desc; /* virtual addr of desc */
@@ -83,6 +86,7 @@ struct ath5k_txq {
83 struct list_head q; /* transmit queue */ 86 struct list_head q; /* transmit queue */
84 spinlock_t lock; /* lock on q and link */ 87 spinlock_t lock; /* lock on q and link */
85 bool setup; 88 bool setup;
89 int txq_len; /* number of queued buffers */
86}; 90};
87 91
88#define ATH5K_LED_MAX_NAME_LEN 31 92#define ATH5K_LED_MAX_NAME_LEN 31
@@ -204,7 +208,6 @@ struct ath5k_softc {
204 spinlock_t txbuflock; 208 spinlock_t txbuflock;
205 unsigned int txbuf_len; /* buf count in txbuf list */ 209 unsigned int txbuf_len; /* buf count in txbuf list */
206 struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ 210 struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
207 struct ath5k_txq *txq; /* main tx queue */
208 struct tasklet_struct txtq; /* tx intr tasklet */ 211 struct tasklet_struct txtq; /* tx intr tasklet */
209 struct ath5k_led tx_led; /* tx led */ 212 struct ath5k_led tx_led; /* tx led */
210 213