aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/base.c
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2009-02-15 12:06:11 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-27 14:52:37 -0500
commitacf3c1a592a070edeede5dfa38c0ce3395357de0 (patch)
tree742fde852e1ee02e1f7bc308f21f41ebcf4ee266 /drivers/net/wireless/ath5k/base.c
parentb5f03956c56d72ad336e5c2c42a025f25d952c30 (diff)
ath5k: move beacon processing to a tasklet
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>
Diffstat (limited to 'drivers/net/wireless/ath5k/base.c')
-rw-r--r--drivers/net/wireless/ath5k/base.c64
1 files changed, 35 insertions, 29 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 8e5620afd2f9..fa6a21646bf8 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -350,6 +350,7 @@ static int ath5k_beacon_setup(struct ath5k_softc *sc,
350static void ath5k_beacon_send(struct ath5k_softc *sc); 350static void ath5k_beacon_send(struct ath5k_softc *sc);
351static void ath5k_beacon_config(struct ath5k_softc *sc); 351static void ath5k_beacon_config(struct ath5k_softc *sc);
352static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); 352static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
353static void ath5k_tasklet_beacon(unsigned long data);
353 354
354static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) 355static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
355{ 356{
@@ -789,6 +790,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
789 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); 790 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
790 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); 791 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
791 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); 792 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
793 tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
792 setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); 794 setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
793 795
794 ret = ath5k_eeprom_read_mac(ah, mac); 796 ret = ath5k_eeprom_read_mac(ah, mac);
@@ -1700,6 +1702,35 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
1700 } 1702 }
1701} 1703}
1702 1704
1705static void ath5k_tasklet_beacon(unsigned long data)
1706{
1707 struct ath5k_softc *sc = (struct ath5k_softc *) data;
1708
1709 /*
1710 * Software beacon alert--time to send a beacon.
1711 *
1712 * In IBSS mode we use this interrupt just to
1713 * keep track of the next TBTT (target beacon
1714 * transmission time) in order to detect wether
1715 * automatic TSF updates happened.
1716 */
1717 if (sc->opmode == NL80211_IFTYPE_ADHOC) {
1718 /* XXX: only if VEOL suppported */
1719 u64 tsf = ath5k_hw_get_tsf64(sc->ah);
1720 sc->nexttbtt += sc->bintval;
1721 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
1722 "SWBA nexttbtt: %x hw_tu: %x "
1723 "TSF: %llx\n",
1724 sc->nexttbtt,
1725 TSF_TO_TU(tsf),
1726 (unsigned long long) tsf);
1727 } else {
1728 spin_lock(&sc->block);
1729 ath5k_beacon_send(sc);
1730 spin_unlock(&sc->block);
1731 }
1732}
1733
1703static void 1734static void
1704ath5k_tasklet_rx(unsigned long data) 1735ath5k_tasklet_rx(unsigned long data)
1705{ 1736{
@@ -2039,9 +2070,8 @@ err_unmap:
2039 * frame contents are done as needed and the slot time is 2070 * frame contents are done as needed and the slot time is
2040 * also adjusted based on current state. 2071 * also adjusted based on current state.
2041 * 2072 *
2042 * this is usually called from interrupt context (ath5k_intr()) 2073 * This is called from software irq context (beacontq or restq
2043 * but also from ath5k_beacon_config() in IBSS mode which in turn 2074 * tasklets) or user context from ath5k_beacon_config.
2044 * can be called from a tasklet and user context
2045 */ 2075 */
2046static void 2076static void
2047ath5k_beacon_send(struct ath5k_softc *sc) 2077ath5k_beacon_send(struct ath5k_softc *sc)
@@ -2391,6 +2421,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
2391 tasklet_kill(&sc->rxtq); 2421 tasklet_kill(&sc->rxtq);
2392 tasklet_kill(&sc->txtq); 2422 tasklet_kill(&sc->txtq);
2393 tasklet_kill(&sc->restq); 2423 tasklet_kill(&sc->restq);
2424 tasklet_kill(&sc->beacontq);
2394 2425
2395 return ret; 2426 return ret;
2396} 2427}
@@ -2421,32 +2452,7 @@ ath5k_intr(int irq, void *dev_id)
2421 tasklet_schedule(&sc->restq); 2452 tasklet_schedule(&sc->restq);
2422 } else { 2453 } else {
2423 if (status & AR5K_INT_SWBA) { 2454 if (status & AR5K_INT_SWBA) {
2424 /* 2455 tasklet_schedule(&sc->beacontq);
2425 * Software beacon alert--time to send a beacon.
2426 * Handle beacon transmission directly; deferring
2427 * this is too slow to meet timing constraints
2428 * under load.
2429 *
2430 * In IBSS mode we use this interrupt just to
2431 * keep track of the next TBTT (target beacon
2432 * transmission time) in order to detect wether
2433 * automatic TSF updates happened.
2434 */
2435 if (sc->opmode == NL80211_IFTYPE_ADHOC) {
2436 /* XXX: only if VEOL suppported */
2437 u64 tsf = ath5k_hw_get_tsf64(ah);
2438 sc->nexttbtt += sc->bintval;
2439 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
2440 "SWBA nexttbtt: %x hw_tu: %x "
2441 "TSF: %llx\n",
2442 sc->nexttbtt,
2443 TSF_TO_TU(tsf),
2444 (unsigned long long) tsf);
2445 } else {
2446 spin_lock(&sc->block);
2447 ath5k_beacon_send(sc);
2448 spin_unlock(&sc->block);
2449 }
2450 } 2456 }
2451 if (status & AR5K_INT_RXEOL) { 2457 if (status & AR5K_INT_RXEOL) {
2452 /* 2458 /*