Skip to content

Commit

Permalink
ath5k: send buffered frames after the beacon
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bob Copeland authored and John W. Linville committed Jul 10, 2009
1 parent 0859339 commit cec8db2
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 11 deletions.
35 changes: 30 additions & 5 deletions drivers/net/wireless/ath/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ static struct pci_driver ath5k_pci_driver = {
* Prototypes - MAC 802.11 stack related functions
*/
static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq);
static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
static int ath5k_reset_wake(struct ath5k_softc *sc);
static int ath5k_start(struct ieee80211_hw *hw);
Expand Down Expand Up @@ -301,7 +303,8 @@ static void ath5k_desc_free(struct ath5k_softc *sc,
static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
struct ath5k_buf *bf);
static int ath5k_txbuf_setup(struct ath5k_softc *sc,
struct ath5k_buf *bf);
struct ath5k_buf *bf,
struct ath5k_txq *txq);
static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
struct ath5k_buf *bf)
{
Expand Down Expand Up @@ -516,6 +519,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
/* Initialize driver private data */
SET_IEEE80211_DEV(hw, &pdev->dev);
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;

Expand Down Expand Up @@ -789,12 +793,18 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
goto err_desc;
}
sc->bhalq = ret;
sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0);
if (IS_ERR(sc->cabq)) {
ATH5K_ERR(sc, "can't setup cab queue\n");
ret = PTR_ERR(sc->cabq);
goto err_bhal;
}

sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
if (IS_ERR(sc->txq)) {
ATH5K_ERR(sc, "can't setup xmit queue\n");
ret = PTR_ERR(sc->txq);
goto err_bhal;
goto err_queues;
}

tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
Expand Down Expand Up @@ -1232,10 +1242,10 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
}

static int
ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
struct ath5k_txq *txq)
{
struct ath5k_hw *ah = sc->ah;
struct ath5k_txq *txq = sc->txq;
struct ath5k_desc *ds = bf->desc;
struct sk_buff *skb = bf->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Expand Down Expand Up @@ -2103,6 +2113,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
{
struct ath5k_buf *bf = sc->bbuf;
struct ath5k_hw *ah = sc->ah;
struct sk_buff *skb;

ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");

Expand Down Expand Up @@ -2156,6 +2167,12 @@ ath5k_beacon_send(struct ath5k_softc *sc)
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
sc->bhalq, (unsigned long long)bf->daddr, bf->desc);

skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
while (skb) {
ath5k_tx_queue(sc->hw, skb, sc->cabq);
skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
}

sc->bsent++;
}

Expand Down Expand Up @@ -2601,6 +2618,14 @@ ath5k_calibrate(unsigned long data)

static int
ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ath5k_softc *sc = hw->priv;

return ath5k_tx_queue(hw, skb, sc->txq);
}

static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq)
{
struct ath5k_softc *sc = hw->priv;
struct ath5k_buf *bf;
Expand Down Expand Up @@ -2646,7 +2671,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)

bf->skb = skb;

if (ath5k_txbuf_setup(sc, bf)) {
if (ath5k_txbuf_setup(sc, bf, txq)) {
bf->skb = NULL;
spin_lock_irqsave(&sc->txbuflock, flags);
list_add_tail(&bf->list, &sc->txbuf);
Expand Down
9 changes: 4 additions & 5 deletions drivers/net/wireless/ath/ath5k/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ struct ath5k_softc {
struct pci_dev *pdev; /* for dma mapping */
void __iomem *iobase; /* address of the device */
struct mutex lock; /* dev-level lock */
/* FIXME: how many does it really need? */
struct ieee80211_tx_queue_stats tx_stats[16];
struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES];
struct ieee80211_low_level_stats ll_stats;
struct ieee80211_hw *hw; /* IEEE 802.11 common */
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
Expand Down Expand Up @@ -171,9 +170,8 @@ struct ath5k_softc {
struct list_head txbuf; /* transmit buffer */
spinlock_t txbuflock;
unsigned int txbuf_len; /* buf count in txbuf list */
struct ath5k_txq txqs[2]; /* beacon and tx */

struct ath5k_txq *txq; /* beacon and tx*/
struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */
struct ath5k_txq *txq; /* main tx queue */
struct tasklet_struct txtq; /* tx intr tasklet */
struct ath5k_led tx_led; /* tx led */

Expand All @@ -187,6 +185,7 @@ struct ath5k_softc {
bintval, /* beacon interval in TU */
bsent;
unsigned int nexttbtt; /* next beacon time in TU */
struct ath5k_txq *cabq; /* content after beacon */

struct timer_list calib_tim; /* calibration timer */
int power_level; /* Requested tx power in dbm */
Expand Down
1 change: 0 additions & 1 deletion drivers/net/wireless/ath/ath5k/qcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
AR5K_QCU_MISC_FRSHED_BCN_SENT_GT |
AR5K_QCU_MISC_CBREXP_DIS |
AR5K_QCU_MISC_RDY_VEOL_POLICY |
AR5K_QCU_MISC_CBREXP_BCN_DIS);

ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
Expand Down

0 comments on commit cec8db2

Please sign in to comment.