Skip to content

Commit

Permalink
ath5k: move beacon processing to a tasklet
Browse files Browse the repository at this point in the history
We currently send beacons directly from the interrupt routine.  This
can hold up interrupt processing in beaconing modes and makes the
ISR somewhat more complex.  Move it to a tasklet like rx and tx.

Changes-licensed-under: 3-Clause-BSD

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 Feb 27, 2009
1 parent b5f0395 commit acf3c1a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 29 deletions.
64 changes: 35 additions & 29 deletions drivers/net/wireless/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ static int ath5k_beacon_setup(struct ath5k_softc *sc,
static void ath5k_beacon_send(struct ath5k_softc *sc);
static void ath5k_beacon_config(struct ath5k_softc *sc);
static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
static void ath5k_tasklet_beacon(unsigned long data);

static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
{
Expand Down Expand Up @@ -789,6 +790,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);

ret = ath5k_eeprom_read_mac(ah, mac);
Expand Down Expand Up @@ -1700,6 +1702,35 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
}
}

static void ath5k_tasklet_beacon(unsigned long data)
{
struct ath5k_softc *sc = (struct ath5k_softc *) data;

/*
* Software beacon alert--time to send a beacon.
*
* In IBSS mode we use this interrupt just to
* keep track of the next TBTT (target beacon
* transmission time) in order to detect wether
* automatic TSF updates happened.
*/
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/* XXX: only if VEOL suppported */
u64 tsf = ath5k_hw_get_tsf64(sc->ah);
sc->nexttbtt += sc->bintval;
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
"SWBA nexttbtt: %x hw_tu: %x "
"TSF: %llx\n",
sc->nexttbtt,
TSF_TO_TU(tsf),
(unsigned long long) tsf);
} else {
spin_lock(&sc->block);
ath5k_beacon_send(sc);
spin_unlock(&sc->block);
}
}

static void
ath5k_tasklet_rx(unsigned long data)
{
Expand Down Expand Up @@ -2039,9 +2070,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
* frame contents are done as needed and the slot time is
* also adjusted based on current state.
*
* this is usually called from interrupt context (ath5k_intr())
* but also from ath5k_beacon_config() in IBSS mode which in turn
* can be called from a tasklet and user context
* This is called from software irq context (beacontq or restq
* tasklets) or user context from ath5k_beacon_config.
*/
static void
ath5k_beacon_send(struct ath5k_softc *sc)
Expand Down Expand Up @@ -2391,6 +2421,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
tasklet_kill(&sc->rxtq);
tasklet_kill(&sc->txtq);
tasklet_kill(&sc->restq);
tasklet_kill(&sc->beacontq);

return ret;
}
Expand Down Expand Up @@ -2421,32 +2452,7 @@ ath5k_intr(int irq, void *dev_id)
tasklet_schedule(&sc->restq);
} else {
if (status & AR5K_INT_SWBA) {
/*
* Software beacon alert--time to send a beacon.
* Handle beacon transmission directly; deferring
* this is too slow to meet timing constraints
* under load.
*
* In IBSS mode we use this interrupt just to
* keep track of the next TBTT (target beacon
* transmission time) in order to detect wether
* automatic TSF updates happened.
*/
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
/* XXX: only if VEOL suppported */
u64 tsf = ath5k_hw_get_tsf64(ah);
sc->nexttbtt += sc->bintval;
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
"SWBA nexttbtt: %x hw_tu: %x "
"TSF: %llx\n",
sc->nexttbtt,
TSF_TO_TU(tsf),
(unsigned long long) tsf);
} else {
spin_lock(&sc->block);
ath5k_beacon_send(sc);
spin_unlock(&sc->block);
}
tasklet_schedule(&sc->beacontq);
}
if (status & AR5K_INT_RXEOL) {
/*
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath5k/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ struct ath5k_softc {
struct ath5k_led tx_led; /* tx led */

spinlock_t block; /* protects beacon */
struct tasklet_struct beacontq; /* beacon intr tasklet */
struct ath5k_buf *bbuf; /* beacon buffer */
unsigned int bhalq, /* SW q for outgoing beacons */
bmisscount, /* missed beacon transmits */
Expand Down

0 comments on commit acf3c1a

Please sign in to comment.