diff options
author | Nick Kossifidis <mick@madwifi-project.org> | 2009-04-30 15:55:47 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-06 15:14:55 -0400 |
commit | 428cbd4ff4d0f2423f49e499f499f04a636cb152 (patch) | |
tree | 1e30461090032e33a7e69abf0ced53ba3be63105 /drivers/net/wireless/ath | |
parent | 1889ba0a48688b639c2b2e9e1b0fd8f84e2c37d1 (diff) |
ath5k: Beaconing fixes
* Write next beacon timer even on AP mode since without this we get
no beacons + ath9k does it too. Docs say that we must write 0 on
this register on AP mode to start TSF increment, we do both to be
on the safe side.
* Fix num_tx_pending function, we never read the register :P that's
why we got all those "beacon queue 7 didn't stop messages".
* Put full prioriy on beacon queue, lock all queues with lower
priority using the arblock and also bypass any arblock by seting
the arblock ignore flag.
* For the CAB queue (do we need this thing ?, it seems crap) since
it's supposed to fire up after each beacon (we don't use it on driver
part, ath9k/MadWiFi does), don't make it DBA gated but instead make
it fire after each beacon by using the beacon sent gated flag.
* Increase bmiss threshold to 10, that's what we used on MadWiFi for
a long time. Also when we have pending frames on the beacon queue (we
got a beacon that didn't make it on the air) it's more likely that
the beacon queue never started, probably due to faulty DBA setting,
so change that "beacon queue didn't stop" message.
Tested this with AP mode and IBSS mode and seems to work fine ;-)
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 64 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/qcu.c | 7 |
3 files changed, 40 insertions, 35 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index d70856a9520e..b48ff7ded325 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1738,35 +1738,6 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1738 | } | 1738 | } |
1739 | } | 1739 | } |
1740 | 1740 | ||
1741 | static void ath5k_tasklet_beacon(unsigned long data) | ||
1742 | { | ||
1743 | struct ath5k_softc *sc = (struct ath5k_softc *) data; | ||
1744 | |||
1745 | /* | ||
1746 | * Software beacon alert--time to send a beacon. | ||
1747 | * | ||
1748 | * In IBSS mode we use this interrupt just to | ||
1749 | * keep track of the next TBTT (target beacon | ||
1750 | * transmission time) in order to detect wether | ||
1751 | * automatic TSF updates happened. | ||
1752 | */ | ||
1753 | if (sc->opmode == NL80211_IFTYPE_ADHOC) { | ||
1754 | /* XXX: only if VEOL suppported */ | ||
1755 | u64 tsf = ath5k_hw_get_tsf64(sc->ah); | ||
1756 | sc->nexttbtt += sc->bintval; | ||
1757 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | ||
1758 | "SWBA nexttbtt: %x hw_tu: %x " | ||
1759 | "TSF: %llx\n", | ||
1760 | sc->nexttbtt, | ||
1761 | TSF_TO_TU(tsf), | ||
1762 | (unsigned long long) tsf); | ||
1763 | } else { | ||
1764 | spin_lock(&sc->block); | ||
1765 | ath5k_beacon_send(sc); | ||
1766 | spin_unlock(&sc->block); | ||
1767 | } | ||
1768 | } | ||
1769 | |||
1770 | static void | 1741 | static void |
1771 | ath5k_tasklet_rx(unsigned long data) | 1742 | ath5k_tasklet_rx(unsigned long data) |
1772 | { | 1743 | { |
@@ -2120,7 +2091,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2120 | sc->bmisscount++; | 2091 | sc->bmisscount++; |
2121 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | 2092 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, |
2122 | "missed %u consecutive beacons\n", sc->bmisscount); | 2093 | "missed %u consecutive beacons\n", sc->bmisscount); |
2123 | if (sc->bmisscount > 3) { /* NB: 3 is a guess */ | 2094 | if (sc->bmisscount > 10) { /* NB: 10 is a guess */ |
2124 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | 2095 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, |
2125 | "stuck beacon time (%u missed)\n", | 2096 | "stuck beacon time (%u missed)\n", |
2126 | sc->bmisscount); | 2097 | sc->bmisscount); |
@@ -2141,10 +2112,12 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2141 | * are still pending on the queue. | 2112 | * are still pending on the queue. |
2142 | */ | 2113 | */ |
2143 | if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { | 2114 | if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { |
2144 | ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq); | 2115 | ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); |
2145 | /* NB: hw still stops DMA, so proceed */ | 2116 | /* NB: hw still stops DMA, so proceed */ |
2146 | } | 2117 | } |
2147 | 2118 | ||
2119 | /* Note: Beacon buffer is updated on beacon_update when mac80211 | ||
2120 | * calls config_interface */ | ||
2148 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); | 2121 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); |
2149 | ath5k_hw_start_tx_dma(ah, sc->bhalq); | 2122 | ath5k_hw_start_tx_dma(ah, sc->bhalq); |
2150 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", | 2123 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", |
@@ -2301,6 +2274,35 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2301 | ath5k_hw_set_imr(ah, sc->imask); | 2274 | ath5k_hw_set_imr(ah, sc->imask); |
2302 | } | 2275 | } |
2303 | 2276 | ||
2277 | static void ath5k_tasklet_beacon(unsigned long data) | ||
2278 | { | ||
2279 | struct ath5k_softc *sc = (struct ath5k_softc *) data; | ||
2280 | |||
2281 | /* | ||
2282 | * Software beacon alert--time to send a beacon. | ||
2283 | * | ||
2284 | * In IBSS mode we use this interrupt just to | ||
2285 | * keep track of the next TBTT (target beacon | ||
2286 | * transmission time) in order to detect wether | ||
2287 | * automatic TSF updates happened. | ||
2288 | */ | ||
2289 | if (sc->opmode == NL80211_IFTYPE_ADHOC) { | ||
2290 | /* XXX: only if VEOL suppported */ | ||
2291 | u64 tsf = ath5k_hw_get_tsf64(sc->ah); | ||
2292 | sc->nexttbtt += sc->bintval; | ||
2293 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | ||
2294 | "SWBA nexttbtt: %x hw_tu: %x " | ||
2295 | "TSF: %llx\n", | ||
2296 | sc->nexttbtt, | ||
2297 | TSF_TO_TU(tsf), | ||
2298 | (unsigned long long) tsf); | ||
2299 | } else { | ||
2300 | spin_lock(&sc->block); | ||
2301 | ath5k_beacon_send(sc); | ||
2302 | spin_unlock(&sc->block); | ||
2303 | } | ||
2304 | } | ||
2305 | |||
2304 | 2306 | ||
2305 | /********************\ | 2307 | /********************\ |
2306 | * Interrupt handling * | 2308 | * Interrupt handling * |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 5f07e876d4bd..579aa0a96ab8 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -736,8 +736,8 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
736 | /* When in AP mode zero timer0 to start TSF */ | 736 | /* When in AP mode zero timer0 to start TSF */ |
737 | if (ah->ah_op_mode == NL80211_IFTYPE_AP) | 737 | if (ah->ah_op_mode == NL80211_IFTYPE_AP) |
738 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); | 738 | ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); |
739 | else | 739 | |
740 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); | 740 | ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); |
741 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); | 741 | ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); |
742 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); | 742 | ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); |
743 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); | 743 | ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 5094c394a4b2..73407b3f53ef 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -160,7 +160,8 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | |||
160 | if (ah->ah_version == AR5K_AR5210) | 160 | if (ah->ah_version == AR5K_AR5210) |
161 | return false; | 161 | return false; |
162 | 162 | ||
163 | pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT); | 163 | pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); |
164 | pending &= AR5K_QCU_STS_FRMPENDCNT; | ||
164 | 165 | ||
165 | /* It's possible to have no frames pending even if TXE | 166 | /* It's possible to have no frames pending even if TXE |
166 | * is set. To indicate that q has not stopped return | 167 | * is set. To indicate that q has not stopped return |
@@ -401,14 +402,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
401 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | 402 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), |
402 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | 403 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << |
403 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | | 404 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | |
405 | AR5K_DCU_MISC_ARBLOCK_IGNORE | | ||
404 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | | 406 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | |
405 | AR5K_DCU_MISC_BCN_ENABLE); | 407 | AR5K_DCU_MISC_BCN_ENABLE); |
406 | break; | 408 | break; |
407 | 409 | ||
408 | case AR5K_TX_QUEUE_CAB: | 410 | case AR5K_TX_QUEUE_CAB: |
409 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | 411 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
410 | AR5K_QCU_MISC_FRSHED_DBA_GT | | 412 | AR5K_QCU_MISC_FRSHED_BCN_SENT_GT | |
411 | AR5K_QCU_MISC_CBREXP_DIS | | 413 | AR5K_QCU_MISC_CBREXP_DIS | |
414 | AR5K_QCU_MISC_RDY_VEOL_POLICY | | ||
412 | AR5K_QCU_MISC_CBREXP_BCN_DIS); | 415 | AR5K_QCU_MISC_CBREXP_BCN_DIS); |
413 | 416 | ||
414 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | 417 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - |