aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2009-07-04 12:59:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:02:28 -0400
commitcec8db23011d2a0a5ec101a0263d79678adf21ba (patch)
tree5449ec9227f9a8332af9c9a22d8d1b90b4ba50e3 /drivers
parent0859339b5c2902a7a4ba1d4c9cf35d882f421e7f (diff)
ath5k: send buffered frames after the beacon
Enable the "Content" After Beacon queue and utilize it to send any buffered frames for power-saving clients. Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c35
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h9
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c1
3 files changed, 34 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index c6e70919435c..87ebc461d74a 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -218,6 +218,8 @@ static struct pci_driver ath5k_pci_driver = {
218 * Prototypes - MAC 802.11 stack related functions 218 * Prototypes - MAC 802.11 stack related functions
219 */ 219 */
220static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); 220static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
221static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
222 struct ath5k_txq *txq);
221static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); 223static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
222static int ath5k_reset_wake(struct ath5k_softc *sc); 224static int ath5k_reset_wake(struct ath5k_softc *sc);
223static int ath5k_start(struct ieee80211_hw *hw); 225static int ath5k_start(struct ieee80211_hw *hw);
@@ -301,7 +303,8 @@ static void ath5k_desc_free(struct ath5k_softc *sc,
301static int ath5k_rxbuf_setup(struct ath5k_softc *sc, 303static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
302 struct ath5k_buf *bf); 304 struct ath5k_buf *bf);
303static int ath5k_txbuf_setup(struct ath5k_softc *sc, 305static int ath5k_txbuf_setup(struct ath5k_softc *sc,
304 struct ath5k_buf *bf); 306 struct ath5k_buf *bf,
307 struct ath5k_txq *txq);
305static inline void ath5k_txbuf_free(struct ath5k_softc *sc, 308static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
306 struct ath5k_buf *bf) 309 struct ath5k_buf *bf)
307{ 310{
@@ -516,6 +519,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
516 /* Initialize driver private data */ 519 /* Initialize driver private data */
517 SET_IEEE80211_DEV(hw, &pdev->dev); 520 SET_IEEE80211_DEV(hw, &pdev->dev);
518 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | 521 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
522 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
519 IEEE80211_HW_SIGNAL_DBM | 523 IEEE80211_HW_SIGNAL_DBM |
520 IEEE80211_HW_NOISE_DBM; 524 IEEE80211_HW_NOISE_DBM;
521 525
@@ -789,12 +793,18 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
789 goto err_desc; 793 goto err_desc;
790 } 794 }
791 sc->bhalq = ret; 795 sc->bhalq = ret;
796 sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
797 if (IS_ERR(sc->cabq)) {
798 ATH5K_ERR(sc, "can't setup cab queue\n");
799 ret = PTR_ERR(sc->cabq);
800 goto err_bhal;
801 }
792 802
793 sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); 803 sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
794 if (IS_ERR(sc->txq)) { 804 if (IS_ERR(sc->txq)) {
795 ATH5K_ERR(sc, "can't setup xmit queue\n"); 805 ATH5K_ERR(sc, "can't setup xmit queue\n");
796 ret = PTR_ERR(sc->txq); 806 ret = PTR_ERR(sc->txq);
797 goto err_bhal; 807 goto err_queues;
798 } 808 }
799 809
800 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); 810 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
@@ -1232,10 +1242,10 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1232} 1242}
1233 1243
1234static int 1244static int
1235ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) 1245ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
1246 struct ath5k_txq *txq)
1236{ 1247{
1237 struct ath5k_hw *ah = sc->ah; 1248 struct ath5k_hw *ah = sc->ah;
1238 struct ath5k_txq *txq = sc->txq;
1239 struct ath5k_desc *ds = bf->desc; 1249 struct ath5k_desc *ds = bf->desc;
1240 struct sk_buff *skb = bf->skb; 1250 struct sk_buff *skb = bf->skb;
1241 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1251 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -2103,6 +2113,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
2103{ 2113{
2104 struct ath5k_buf *bf = sc->bbuf; 2114 struct ath5k_buf *bf = sc->bbuf;
2105 struct ath5k_hw *ah = sc->ah; 2115 struct ath5k_hw *ah = sc->ah;
2116 struct sk_buff *skb;
2106 2117
2107 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); 2118 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
2108 2119
@@ -2156,6 +2167,12 @@ ath5k_beacon_send(struct ath5k_softc *sc)
2156 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", 2167 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
2157 sc->bhalq, (unsigned long long)bf->daddr, bf->desc); 2168 sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
2158 2169
2170 skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
2171 while (skb) {
2172 ath5k_tx_queue(sc->hw, skb, sc->cabq);
2173 skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
2174 }
2175
2159 sc->bsent++; 2176 sc->bsent++;
2160} 2177}
2161 2178
@@ -2603,6 +2620,14 @@ static int
2603ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 2620ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
2604{ 2621{
2605 struct ath5k_softc *sc = hw->priv; 2622 struct ath5k_softc *sc = hw->priv;
2623
2624 return ath5k_tx_queue(hw, skb, sc->txq);
2625}
2626
2627static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
2628 struct ath5k_txq *txq)
2629{
2630 struct ath5k_softc *sc = hw->priv;
2606 struct ath5k_buf *bf; 2631 struct ath5k_buf *bf;
2607 unsigned long flags; 2632 unsigned long flags;
2608 int hdrlen; 2633 int hdrlen;
@@ -2646,7 +2671,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
2646 2671
2647 bf->skb = skb; 2672 bf->skb = skb;
2648 2673
2649 if (ath5k_txbuf_setup(sc, bf)) { 2674 if (ath5k_txbuf_setup(sc, bf, txq)) {
2650 bf->skb = NULL; 2675 bf->skb = NULL;
2651 spin_lock_irqsave(&sc->txbuflock, flags); 2676 spin_lock_irqsave(&sc->txbuflock, flags);
2652 list_add_tail(&bf->list, &sc->txbuf); 2677 list_add_tail(&bf->list, &sc->txbuf);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index f9b7f2f819b7..65e75fb54482 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -114,8 +114,7 @@ struct ath5k_softc {
114 struct pci_dev *pdev; /* for dma mapping */ 114 struct pci_dev *pdev; /* for dma mapping */
115 void __iomem *iobase; /* address of the device */ 115 void __iomem *iobase; /* address of the device */
116 struct mutex lock; /* dev-level lock */ 116 struct mutex lock; /* dev-level lock */
117 /* FIXME: how many does it really need? */ 117 struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES];
118 struct ieee80211_tx_queue_stats tx_stats[16];
119 struct ieee80211_low_level_stats ll_stats; 118 struct ieee80211_low_level_stats ll_stats;
120 struct ieee80211_hw *hw; /* IEEE 802.11 common */ 119 struct ieee80211_hw *hw; /* IEEE 802.11 common */
121 struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; 120 struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
@@ -171,9 +170,8 @@ struct ath5k_softc {
171 struct list_head txbuf; /* transmit buffer */ 170 struct list_head txbuf; /* transmit buffer */
172 spinlock_t txbuflock; 171 spinlock_t txbuflock;
173 unsigned int txbuf_len; /* buf count in txbuf list */ 172 unsigned int txbuf_len; /* buf count in txbuf list */
174 struct ath5k_txq txqs[2]; /* beacon and tx */ 173 struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
175 174 struct ath5k_txq *txq; /* main tx queue */
176 struct ath5k_txq *txq; /* beacon and tx*/
177 struct tasklet_struct txtq; /* tx intr tasklet */ 175 struct tasklet_struct txtq; /* tx intr tasklet */
178 struct ath5k_led tx_led; /* tx led */ 176 struct ath5k_led tx_led; /* tx led */
179 177
@@ -187,6 +185,7 @@ struct ath5k_softc {
187 bintval, /* beacon interval in TU */ 185 bintval, /* beacon interval in TU */
188 bsent; 186 bsent;
189 unsigned int nexttbtt; /* next beacon time in TU */ 187 unsigned int nexttbtt; /* next beacon time in TU */
188 struct ath5k_txq *cabq; /* content after beacon */
190 189
191 struct timer_list calib_tim; /* calibration timer */ 190 struct timer_list calib_tim; /* calibration timer */
192 int power_level; /* Requested tx power in dbm */ 191 int power_level; /* Requested tx power in dbm */
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 73407b3f53ef..6d5aaf00d8bb 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -411,7 +411,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
411 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), 411 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
412 AR5K_QCU_MISC_FRSHED_BCN_SENT_GT | 412 AR5K_QCU_MISC_FRSHED_BCN_SENT_GT |
413 AR5K_QCU_MISC_CBREXP_DIS | 413 AR5K_QCU_MISC_CBREXP_DIS |
414 AR5K_QCU_MISC_RDY_VEOL_POLICY |
415 AR5K_QCU_MISC_CBREXP_BCN_DIS); 414 AR5K_QCU_MISC_CBREXP_BCN_DIS);
416 415
417 ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - 416 ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -