diff options
author | Bob Copeland <me@bobcopeland.com> | 2009-07-04 12:59:51 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-10 15:02:28 -0400 |
commit | cec8db23011d2a0a5ec101a0263d79678adf21ba (patch) | |
tree | 5449ec9227f9a8332af9c9a22d8d1b90b4ba50e3 /drivers | |
parent | 0859339b5c2902a7a4ba1d4c9cf35d882f421e7f (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.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/qcu.c | 1 |
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 | */ |
220 | static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | 220 | static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); |
221 | static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
222 | struct ath5k_txq *txq); | ||
221 | static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); | 223 | static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); |
222 | static int ath5k_reset_wake(struct ath5k_softc *sc); | 224 | static int ath5k_reset_wake(struct ath5k_softc *sc); |
223 | static int ath5k_start(struct ieee80211_hw *hw); | 225 | static int ath5k_start(struct ieee80211_hw *hw); |
@@ -301,7 +303,8 @@ static void ath5k_desc_free(struct ath5k_softc *sc, | |||
301 | static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | 303 | static int ath5k_rxbuf_setup(struct ath5k_softc *sc, |
302 | struct ath5k_buf *bf); | 304 | struct ath5k_buf *bf); |
303 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | 305 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, |
304 | struct ath5k_buf *bf); | 306 | struct ath5k_buf *bf, |
307 | struct ath5k_txq *txq); | ||
305 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | 308 | static 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 | ||
1234 | static int | 1244 | static int |
1235 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | 1245 | ath5k_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 | |||
2603 | ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 2620 | ath5k_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 | |||
2627 | static 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 - |