if_ath.c (235676) | if_ath.c (235679) |
---|---|
1/*- 2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath.c 235676 2012-05-20 02:05:10Z adrian $"); | 31__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath.c 235679 2012-05-20 02:49:42Z adrian $"); |
32 33/* 34 * Driver for the Atheros Wireless LAN controller. 35 * 36 * This software is derived from work of Atsushi Onoe; his contribution 37 * is greatly appreciated. 38 */ 39 --- 63 unchanged lines hidden (view full) --- 103#include <dev/ath/if_ath_debug.h> 104#include <dev/ath/if_ath_misc.h> 105#include <dev/ath/if_ath_tsf.h> 106#include <dev/ath/if_ath_tx.h> 107#include <dev/ath/if_ath_sysctl.h> 108#include <dev/ath/if_ath_led.h> 109#include <dev/ath/if_ath_keycache.h> 110#include <dev/ath/if_ath_rx.h> | 32 33/* 34 * Driver for the Atheros Wireless LAN controller. 35 * 36 * This software is derived from work of Atsushi Onoe; his contribution 37 * is greatly appreciated. 38 */ 39 --- 63 unchanged lines hidden (view full) --- 103#include <dev/ath/if_ath_debug.h> 104#include <dev/ath/if_ath_misc.h> 105#include <dev/ath/if_ath_tsf.h> 106#include <dev/ath/if_ath_tx.h> 107#include <dev/ath/if_ath_sysctl.h> 108#include <dev/ath/if_ath_led.h> 109#include <dev/ath/if_ath_keycache.h> 110#include <dev/ath/if_ath_rx.h> |
111#include <dev/ath/if_ath_beacon.h> |
|
111#include <dev/ath/if_athdfs.h> 112 113#ifdef ATH_TX99_DIAG 114#include <dev/ath/ath_tx99/ath_tx99.h> 115#endif 116 117#define ATH_KTR_INTR KTR_SPARE4 118#define ATH_KTR_ERR KTR_SPARE3 --- 35 unchanged lines hidden (view full) --- 154static void ath_update_promisc(struct ifnet *); 155static void ath_setslottime(struct ath_softc *); 156static void ath_updateslot(struct ifnet *); 157static int ath_beaconq_setup(struct ath_hal *); 158static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *); 159static void ath_beacon_update(struct ieee80211vap *, int item); 160static void ath_beacon_setup(struct ath_softc *, struct ath_buf *); 161static void ath_beacon_proc(void *, int); | 112#include <dev/ath/if_athdfs.h> 113 114#ifdef ATH_TX99_DIAG 115#include <dev/ath/ath_tx99/ath_tx99.h> 116#endif 117 118#define ATH_KTR_INTR KTR_SPARE4 119#define ATH_KTR_ERR KTR_SPARE3 --- 35 unchanged lines hidden (view full) --- 155static void ath_update_promisc(struct ifnet *); 156static void ath_setslottime(struct ath_softc *); 157static void ath_updateslot(struct ifnet *); 158static int ath_beaconq_setup(struct ath_hal *); 159static int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *); 160static void ath_beacon_update(struct ieee80211vap *, int item); 161static void ath_beacon_setup(struct ath_softc *, struct ath_buf *); 162static void ath_beacon_proc(void *, int); |
162static struct ath_buf *ath_beacon_generate(struct ath_softc *, 163 struct ieee80211vap *); | |
164static void ath_bstuck_proc(void *, int); 165static void ath_reset_proc(void *, int); 166static void ath_beacon_return(struct ath_softc *, struct ath_buf *); 167static void ath_beacon_free(struct ath_softc *); 168static void ath_descdma_cleanup(struct ath_softc *sc, 169 struct ath_descdma *, ath_bufhead *); 170static int ath_desc_alloc(struct ath_softc *); 171static void ath_desc_free(struct ath_softc *); 172static struct ieee80211_node *ath_node_alloc(struct ieee80211vap *, 173 const uint8_t [IEEE80211_ADDR_LEN]); 174static void ath_node_cleanup(struct ieee80211_node *); 175static void ath_node_free(struct ieee80211_node *); 176static void ath_node_getsignal(const struct ieee80211_node *, 177 int8_t *, int8_t *); 178static void ath_txq_init(struct ath_softc *sc, struct ath_txq *, int); 179static struct ath_txq *ath_txq_setup(struct ath_softc*, int qtype, int subtype); 180static int ath_tx_setup(struct ath_softc *, int, int); | 163static void ath_bstuck_proc(void *, int); 164static void ath_reset_proc(void *, int); 165static void ath_beacon_return(struct ath_softc *, struct ath_buf *); 166static void ath_beacon_free(struct ath_softc *); 167static void ath_descdma_cleanup(struct ath_softc *sc, 168 struct ath_descdma *, ath_bufhead *); 169static int ath_desc_alloc(struct ath_softc *); 170static void ath_desc_free(struct ath_softc *); 171static struct ieee80211_node *ath_node_alloc(struct ieee80211vap *, 172 const uint8_t [IEEE80211_ADDR_LEN]); 173static void ath_node_cleanup(struct ieee80211_node *); 174static void ath_node_free(struct ieee80211_node *); 175static void ath_node_getsignal(const struct ieee80211_node *, 176 int8_t *, int8_t *); 177static void ath_txq_init(struct ath_softc *sc, struct ath_txq *, int); 178static struct ath_txq *ath_txq_setup(struct ath_softc*, int qtype, int subtype); 179static int ath_tx_setup(struct ath_softc *, int, int); |
181static int ath_wme_update(struct ieee80211com *); | |
182static void ath_tx_cleanupq(struct ath_softc *, struct ath_txq *); 183static void ath_tx_cleanup(struct ath_softc *); 184static void ath_tx_proc_q0(void *, int); 185static void ath_tx_proc_q0123(void *, int); 186static void ath_tx_proc(void *, int); 187static void ath_txq_sched_tasklet(void *, int); 188static int ath_chan_set(struct ath_softc *, struct ieee80211_channel *); 189static void ath_draintxq(struct ath_softc *, ATH_RESET_TYPE reset_type); --- 18 unchanged lines hidden (view full) --- 208static int ath_rate_setup(struct ath_softc *, u_int mode); 209static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode); 210 211static void ath_announce(struct ath_softc *); 212 213static void ath_dfs_tasklet(void *, int); 214 215#ifdef IEEE80211_SUPPORT_TDMA | 180static void ath_tx_cleanupq(struct ath_softc *, struct ath_txq *); 181static void ath_tx_cleanup(struct ath_softc *); 182static void ath_tx_proc_q0(void *, int); 183static void ath_tx_proc_q0123(void *, int); 184static void ath_tx_proc(void *, int); 185static void ath_txq_sched_tasklet(void *, int); 186static int ath_chan_set(struct ath_softc *, struct ieee80211_channel *); 187static void ath_draintxq(struct ath_softc *, ATH_RESET_TYPE reset_type); --- 18 unchanged lines hidden (view full) --- 206static int ath_rate_setup(struct ath_softc *, u_int mode); 207static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode); 208 209static void ath_announce(struct ath_softc *); 210 211static void ath_dfs_tasklet(void *, int); 212 213#ifdef IEEE80211_SUPPORT_TDMA |
216static void ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, 217 u_int32_t bintval); 218static void ath_tdma_bintvalsetup(struct ath_softc *sc, 219 const struct ieee80211_tdma_state *tdma); 220static void ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap); 221static void ath_tdma_update(struct ieee80211_node *ni, 222 const struct ieee80211_tdma_param *tdma, int); 223static void ath_tdma_beacon_send(struct ath_softc *sc, 224 struct ieee80211vap *vap); | 214#include <dev/ath/if_ath_tdma.h> 215#endif |
225 | 216 |
217#if 0 |
|
226#define TDMA_EP_MULTIPLIER (1<<10) /* pow2 to optimize out * and / */ 227#define TDMA_LPF_LEN 6 228#define TDMA_DUMMY_MARKER 0x127 229#define TDMA_EP_MUL(x, mul) ((x) * (mul)) 230#define TDMA_IN(x) (TDMA_EP_MUL((x), TDMA_EP_MULTIPLIER)) 231#define TDMA_LPF(x, y, len) \ 232 ((x != TDMA_DUMMY_MARKER) ? (((x) * ((len)-1) + (y)) / (len)) : (y)) 233#define TDMA_SAMPLE(x, y) do { \ --- 24 unchanged lines hidden (view full) --- 258SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf, 259 0, "rx buffers allocated"); 260TUNABLE_INT("hw.ath.rxbuf", &ath_rxbuf); 261static int ath_txbuf = ATH_TXBUF; /* # tx buffers to allocate */ 262SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RW, &ath_txbuf, 263 0, "tx buffers allocated"); 264TUNABLE_INT("hw.ath.txbuf", &ath_txbuf); 265 | 218#define TDMA_EP_MULTIPLIER (1<<10) /* pow2 to optimize out * and / */ 219#define TDMA_LPF_LEN 6 220#define TDMA_DUMMY_MARKER 0x127 221#define TDMA_EP_MUL(x, mul) ((x) * (mul)) 222#define TDMA_IN(x) (TDMA_EP_MUL((x), TDMA_EP_MULTIPLIER)) 223#define TDMA_LPF(x, y, len) \ 224 ((x != TDMA_DUMMY_MARKER) ? (((x) * ((len)-1) + (y)) / (len)) : (y)) 225#define TDMA_SAMPLE(x, y) do { \ --- 24 unchanged lines hidden (view full) --- 250SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf, 251 0, "rx buffers allocated"); 252TUNABLE_INT("hw.ath.rxbuf", &ath_rxbuf); 253static int ath_txbuf = ATH_TXBUF; /* # tx buffers to allocate */ 254SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RW, &ath_txbuf, 255 0, "tx buffers allocated"); 256TUNABLE_INT("hw.ath.txbuf", &ath_txbuf); 257 |
266static int ath_bstuck_threshold = 4; /* max missed beacons */ | 258int ath_bstuck_threshold = 4; /* max missed beacons */ |
267SYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold, 268 0, "max missed beacon xmits before chip reset"); 269 270MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers"); 271 272#define HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20) 273#define HAL_MODE_HT40 \ 274 (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \ --- 2341 unchanged lines hidden (view full) --- 2616 /* NB: for dynamic turbo, don't enable any other interrupts */ 2617 qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE; 2618 return ath_hal_setuptxqueue(ah, HAL_TX_QUEUE_BEACON, &qi); 2619} 2620 2621/* 2622 * Setup the transmit queue parameters for the beacon queue. 2623 */ | 259SYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold, 260 0, "max missed beacon xmits before chip reset"); 261 262MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers"); 263 264#define HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20) 265#define HAL_MODE_HT40 \ 266 (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \ --- 2341 unchanged lines hidden (view full) --- 2608 /* NB: for dynamic turbo, don't enable any other interrupts */ 2609 qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE; 2610 return ath_hal_setuptxqueue(ah, HAL_TX_QUEUE_BEACON, &qi); 2611} 2612 2613/* 2614 * Setup the transmit queue parameters for the beacon queue. 2615 */ |
2624static int | 2616int |
2625ath_beaconq_config(struct ath_softc *sc) 2626{ 2627#define ATH_EXPONENT_TO_VALUE(v) ((1<<(v))-1) 2628 struct ieee80211com *ic = sc->sc_ifp->if_l2com; 2629 struct ath_hal *ah = sc->sc_ah; 2630 HAL_TXQ_INFO qi; 2631 2632 ath_hal_gettxqueueprops(ah, sc->sc_bhalq, &qi); --- 338 unchanged lines hidden (view full) --- 2971 /* NB: cabq traffic should already be queued and primed */ 2972 ath_hal_puttxbuf(ah, sc->sc_bhalq, bfaddr); 2973 ath_hal_txstart(ah, sc->sc_bhalq); 2974 2975 sc->sc_stats.ast_be_xmit++; 2976 } 2977} 2978 | 2617ath_beaconq_config(struct ath_softc *sc) 2618{ 2619#define ATH_EXPONENT_TO_VALUE(v) ((1<<(v))-1) 2620 struct ieee80211com *ic = sc->sc_ifp->if_l2com; 2621 struct ath_hal *ah = sc->sc_ah; 2622 HAL_TXQ_INFO qi; 2623 2624 ath_hal_gettxqueueprops(ah, sc->sc_bhalq, &qi); --- 338 unchanged lines hidden (view full) --- 2963 /* NB: cabq traffic should already be queued and primed */ 2964 ath_hal_puttxbuf(ah, sc->sc_bhalq, bfaddr); 2965 ath_hal_txstart(ah, sc->sc_bhalq); 2966 2967 sc->sc_stats.ast_be_xmit++; 2968 } 2969} 2970 |
2979static struct ath_buf * | 2971struct ath_buf * |
2980ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap) 2981{ 2982 struct ath_vap *avp = ATH_VAP(vap); 2983 struct ath_txq *cabq = sc->sc_cabq; 2984 struct ath_buf *bf; 2985 struct mbuf *m; 2986 int nmcastq, error; 2987 --- 883 unchanged lines hidden (view full) --- 3871 } 3872#undef ATH_TXOP_TO_US 3873#undef ATH_EXPONENT_TO_VALUE 3874} 3875 3876/* 3877 * Callback from the 802.11 layer to update WME parameters. 3878 */ | 2972ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap) 2973{ 2974 struct ath_vap *avp = ATH_VAP(vap); 2975 struct ath_txq *cabq = sc->sc_cabq; 2976 struct ath_buf *bf; 2977 struct mbuf *m; 2978 int nmcastq, error; 2979 --- 883 unchanged lines hidden (view full) --- 3863 } 3864#undef ATH_TXOP_TO_US 3865#undef ATH_EXPONENT_TO_VALUE 3866} 3867 3868/* 3869 * Callback from the 802.11 layer to update WME parameters. 3870 */ |
3879static int | 3871int |
3880ath_wme_update(struct ieee80211com *ic) 3881{ 3882 struct ath_softc *sc = ic->ic_ifp->if_softc; 3883 3884 return !ath_txq_update(sc, WME_AC_BE) || 3885 !ath_txq_update(sc, WME_AC_BK) || 3886 !ath_txq_update(sc, WME_AC_VI) || 3887 !ath_txq_update(sc, WME_AC_VO) ? EIO : 0; --- 1757 unchanged lines hidden (view full) --- 5645 if (ath_rxbuf != ATH_RXBUF) 5646 if_printf(ifp, "using %u rx buffers\n", ath_rxbuf); 5647 if (ath_txbuf != ATH_TXBUF) 5648 if_printf(ifp, "using %u tx buffers\n", ath_txbuf); 5649 if (sc->sc_mcastkey && bootverbose) 5650 if_printf(ifp, "using multicast key search\n"); 5651} 5652 | 3872ath_wme_update(struct ieee80211com *ic) 3873{ 3874 struct ath_softc *sc = ic->ic_ifp->if_softc; 3875 3876 return !ath_txq_update(sc, WME_AC_BE) || 3877 !ath_txq_update(sc, WME_AC_BK) || 3878 !ath_txq_update(sc, WME_AC_VI) || 3879 !ath_txq_update(sc, WME_AC_VO) ? EIO : 0; --- 1757 unchanged lines hidden (view full) --- 5637 if (ath_rxbuf != ATH_RXBUF) 5638 if_printf(ifp, "using %u rx buffers\n", ath_rxbuf); 5639 if (ath_txbuf != ATH_TXBUF) 5640 if_printf(ifp, "using %u tx buffers\n", ath_txbuf); 5641 if (sc->sc_mcastkey && bootverbose) 5642 if_printf(ifp, "using multicast key search\n"); 5643} 5644 |
5653#ifdef IEEE80211_SUPPORT_TDMA | |
5654static void | 5645static void |
5655ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval) 5656{ 5657 struct ath_hal *ah = sc->sc_ah; 5658 HAL_BEACON_TIMERS bt; 5659 5660 bt.bt_intval = bintval | HAL_BEACON_ENA; 5661 bt.bt_nexttbtt = nexttbtt; 5662 bt.bt_nextdba = (nexttbtt<<3) - sc->sc_tdmadbaprep; 5663 bt.bt_nextswba = (nexttbtt<<3) - sc->sc_tdmaswbaprep; 5664 bt.bt_nextatim = nexttbtt+1; 5665 /* Enables TBTT, DBA, SWBA timers by default */ 5666 bt.bt_flags = 0; 5667 ath_hal_beaconsettimers(ah, &bt); 5668} 5669 5670/* 5671 * Calculate the beacon interval. This is periodic in the 5672 * superframe for the bss. We assume each station is configured 5673 * identically wrt transmit rate so the guard time we calculate 5674 * above will be the same on all stations. Note we need to 5675 * factor in the xmit time because the hardware will schedule 5676 * a frame for transmit if the start of the frame is within 5677 * the burst time. When we get hardware that properly kills 5678 * frames in the PCU we can reduce/eliminate the guard time. 5679 * 5680 * Roundup to 1024 is so we have 1 TU buffer in the guard time 5681 * to deal with the granularity of the nexttbtt timer. 11n MAC's 5682 * with 1us timer granularity should allow us to reduce/eliminate 5683 * this. 5684 */ 5685static void 5686ath_tdma_bintvalsetup(struct ath_softc *sc, 5687 const struct ieee80211_tdma_state *tdma) 5688{ 5689 /* copy from vap state (XXX check all vaps have same value?) */ 5690 sc->sc_tdmaslotlen = tdma->tdma_slotlen; 5691 5692 sc->sc_tdmabintval = roundup((sc->sc_tdmaslotlen+sc->sc_tdmaguard) * 5693 tdma->tdma_slotcnt, 1024); 5694 sc->sc_tdmabintval >>= 10; /* TSF -> TU */ 5695 if (sc->sc_tdmabintval & 1) 5696 sc->sc_tdmabintval++; 5697 5698 if (tdma->tdma_slot == 0) { 5699 /* 5700 * Only slot 0 beacons; other slots respond. 5701 */ 5702 sc->sc_imask |= HAL_INT_SWBA; 5703 sc->sc_tdmaswba = 0; /* beacon immediately */ 5704 } else { 5705 /* XXX all vaps must be slot 0 or slot !0 */ 5706 sc->sc_imask &= ~HAL_INT_SWBA; 5707 } 5708} 5709 5710/* 5711 * Max 802.11 overhead. This assumes no 4-address frames and 5712 * the encapsulation done by ieee80211_encap (llc). We also 5713 * include potential crypto overhead. 5714 */ 5715#define IEEE80211_MAXOVERHEAD \ 5716 (sizeof(struct ieee80211_qosframe) \ 5717 + sizeof(struct llc) \ 5718 + IEEE80211_ADDR_LEN \ 5719 + IEEE80211_WEP_IVLEN \ 5720 + IEEE80211_WEP_KIDLEN \ 5721 + IEEE80211_WEP_CRCLEN \ 5722 + IEEE80211_WEP_MICLEN \ 5723 + IEEE80211_CRC_LEN) 5724 5725/* 5726 * Setup initially for tdma operation. Start the beacon 5727 * timers and enable SWBA if we are slot 0. Otherwise 5728 * we wait for slot 0 to arrive so we can sync up before 5729 * starting to transmit. 5730 */ 5731static void 5732ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap) 5733{ 5734 struct ath_hal *ah = sc->sc_ah; 5735 struct ifnet *ifp = sc->sc_ifp; 5736 struct ieee80211com *ic = ifp->if_l2com; 5737 const struct ieee80211_txparam *tp; 5738 const struct ieee80211_tdma_state *tdma = NULL; 5739 int rix; 5740 5741 if (vap == NULL) { 5742 vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */ 5743 if (vap == NULL) { 5744 if_printf(ifp, "%s: no vaps?\n", __func__); 5745 return; 5746 } 5747 } 5748 /* XXX should take a locked ref to iv_bss */ 5749 tp = vap->iv_bss->ni_txparms; 5750 /* 5751 * Calculate the guard time for each slot. This is the 5752 * time to send a maximal-size frame according to the 5753 * fixed/lowest transmit rate. Note that the interface 5754 * mtu does not include the 802.11 overhead so we must 5755 * tack that on (ath_hal_computetxtime includes the 5756 * preamble and plcp in it's calculation). 5757 */ 5758 tdma = vap->iv_tdma; 5759 if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) 5760 rix = ath_tx_findrix(sc, tp->ucastrate); 5761 else 5762 rix = ath_tx_findrix(sc, tp->mcastrate); 5763 /* XXX short preamble assumed */ 5764 sc->sc_tdmaguard = ath_hal_computetxtime(ah, sc->sc_currates, 5765 ifp->if_mtu + IEEE80211_MAXOVERHEAD, rix, AH_TRUE); 5766 5767 ath_hal_intrset(ah, 0); 5768 5769 ath_beaconq_config(sc); /* setup h/w beacon q */ 5770 if (sc->sc_setcca) 5771 ath_hal_setcca(ah, AH_FALSE); /* disable CCA */ 5772 ath_tdma_bintvalsetup(sc, tdma); /* calculate beacon interval */ 5773 ath_tdma_settimers(sc, sc->sc_tdmabintval, 5774 sc->sc_tdmabintval | HAL_BEACON_RESET_TSF); 5775 sc->sc_syncbeacon = 0; 5776 5777 sc->sc_avgtsfdeltap = TDMA_DUMMY_MARKER; 5778 sc->sc_avgtsfdeltam = TDMA_DUMMY_MARKER; 5779 5780 ath_hal_intrset(ah, sc->sc_imask); 5781 5782 DPRINTF(sc, ATH_DEBUG_TDMA, "%s: slot %u len %uus cnt %u " 5783 "bsched %u guard %uus bintval %u TU dba prep %u\n", __func__, 5784 tdma->tdma_slot, tdma->tdma_slotlen, tdma->tdma_slotcnt, 5785 tdma->tdma_bintval, sc->sc_tdmaguard, sc->sc_tdmabintval, 5786 sc->sc_tdmadbaprep); 5787} 5788 5789/* 5790 * Update tdma operation. Called from the 802.11 layer 5791 * when a beacon is received from the TDMA station operating 5792 * in the slot immediately preceding us in the bss. Use 5793 * the rx timestamp for the beacon frame to update our 5794 * beacon timers so we follow their schedule. Note that 5795 * by using the rx timestamp we implicitly include the 5796 * propagation delay in our schedule. 5797 */ 5798static void 5799ath_tdma_update(struct ieee80211_node *ni, 5800 const struct ieee80211_tdma_param *tdma, int changed) 5801{ 5802#define TSF_TO_TU(_h,_l) \ 5803 ((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10)) 5804#define TU_TO_TSF(_tu) (((u_int64_t)(_tu)) << 10) 5805 struct ieee80211vap *vap = ni->ni_vap; 5806 struct ieee80211com *ic = ni->ni_ic; 5807 struct ath_softc *sc = ic->ic_ifp->if_softc; 5808 struct ath_hal *ah = sc->sc_ah; 5809 const HAL_RATE_TABLE *rt = sc->sc_currates; 5810 u_int64_t tsf, rstamp, nextslot, nexttbtt; 5811 u_int32_t txtime, nextslottu; 5812 int32_t tudelta, tsfdelta; 5813 const struct ath_rx_status *rs; 5814 int rix; 5815 5816 sc->sc_stats.ast_tdma_update++; 5817 5818 /* 5819 * Check for and adopt configuration changes. 5820 */ 5821 if (changed != 0) { 5822 const struct ieee80211_tdma_state *ts = vap->iv_tdma; 5823 5824 ath_tdma_bintvalsetup(sc, ts); 5825 if (changed & TDMA_UPDATE_SLOTLEN) 5826 ath_wme_update(ic); 5827 5828 DPRINTF(sc, ATH_DEBUG_TDMA, 5829 "%s: adopt slot %u slotcnt %u slotlen %u us " 5830 "bintval %u TU\n", __func__, 5831 ts->tdma_slot, ts->tdma_slotcnt, ts->tdma_slotlen, 5832 sc->sc_tdmabintval); 5833 5834 /* XXX right? */ 5835 ath_hal_intrset(ah, sc->sc_imask); 5836 /* NB: beacon timers programmed below */ 5837 } 5838 5839 /* extend rx timestamp to 64 bits */ 5840 rs = sc->sc_lastrs; 5841 tsf = ath_hal_gettsf64(ah); 5842 rstamp = ath_extend_tsf(sc, rs->rs_tstamp, tsf); 5843 /* 5844 * The rx timestamp is set by the hardware on completing 5845 * reception (at the point where the rx descriptor is DMA'd 5846 * to the host). To find the start of our next slot we 5847 * must adjust this time by the time required to send 5848 * the packet just received. 5849 */ 5850 rix = rt->rateCodeToIndex[rs->rs_rate]; 5851 txtime = ath_hal_computetxtime(ah, rt, rs->rs_datalen, rix, 5852 rt->info[rix].shortPreamble); 5853 /* NB: << 9 is to cvt to TU and /2 */ 5854 nextslot = (rstamp - txtime) + (sc->sc_tdmabintval << 9); 5855 nextslottu = TSF_TO_TU(nextslot>>32, nextslot) & HAL_BEACON_PERIOD; 5856 5857 /* 5858 * Retrieve the hardware NextTBTT in usecs 5859 * and calculate the difference between what the 5860 * other station thinks and what we have programmed. This 5861 * lets us figure how to adjust our timers to match. The 5862 * adjustments are done by pulling the TSF forward and possibly 5863 * rewriting the beacon timers. 5864 */ 5865 nexttbtt = ath_hal_getnexttbtt(ah); 5866 tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD + 1)) - nexttbtt); 5867 5868 DPRINTF(sc, ATH_DEBUG_TDMA_TIMER, 5869 "tsfdelta %d avg +%d/-%d\n", tsfdelta, 5870 TDMA_AVG(sc->sc_avgtsfdeltap), TDMA_AVG(sc->sc_avgtsfdeltam)); 5871 5872 if (tsfdelta < 0) { 5873 TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0); 5874 TDMA_SAMPLE(sc->sc_avgtsfdeltam, -tsfdelta); 5875 tsfdelta = -tsfdelta % 1024; 5876 nextslottu++; 5877 } else if (tsfdelta > 0) { 5878 TDMA_SAMPLE(sc->sc_avgtsfdeltap, tsfdelta); 5879 TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0); 5880 tsfdelta = 1024 - (tsfdelta % 1024); 5881 nextslottu++; 5882 } else { 5883 TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0); 5884 TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0); 5885 } 5886 tudelta = nextslottu - TSF_TO_TU(nexttbtt >> 32, nexttbtt); 5887 5888 /* 5889 * Copy sender's timetstamp into tdma ie so they can 5890 * calculate roundtrip time. We submit a beacon frame 5891 * below after any timer adjustment. The frame goes out 5892 * at the next TBTT so the sender can calculate the 5893 * roundtrip by inspecting the tdma ie in our beacon frame. 5894 * 5895 * NB: This tstamp is subtlely preserved when 5896 * IEEE80211_BEACON_TDMA is marked (e.g. when the 5897 * slot position changes) because ieee80211_add_tdma 5898 * skips over the data. 5899 */ 5900 memcpy(ATH_VAP(vap)->av_boff.bo_tdma + 5901 __offsetof(struct ieee80211_tdma_param, tdma_tstamp), 5902 &ni->ni_tstamp.data, 8); 5903#if 0 5904 DPRINTF(sc, ATH_DEBUG_TDMA_TIMER, 5905 "tsf %llu nextslot %llu (%d, %d) nextslottu %u nexttbtt %llu (%d)\n", 5906 (unsigned long long) tsf, (unsigned long long) nextslot, 5907 (int)(nextslot - tsf), tsfdelta, nextslottu, nexttbtt, tudelta); 5908#endif 5909 /* 5910 * Adjust the beacon timers only when pulling them forward 5911 * or when going back by less than the beacon interval. 5912 * Negative jumps larger than the beacon interval seem to 5913 * cause the timers to stop and generally cause instability. 5914 * This basically filters out jumps due to missed beacons. 5915 */ 5916 if (tudelta != 0 && (tudelta > 0 || -tudelta < sc->sc_tdmabintval)) { 5917 ath_tdma_settimers(sc, nextslottu, sc->sc_tdmabintval); 5918 sc->sc_stats.ast_tdma_timers++; 5919 } 5920 if (tsfdelta > 0) { 5921 ath_hal_adjusttsf(ah, tsfdelta); 5922 sc->sc_stats.ast_tdma_tsf++; 5923 } 5924 ath_tdma_beacon_send(sc, vap); /* prepare response */ 5925#undef TU_TO_TSF 5926#undef TSF_TO_TU 5927} 5928 5929/* 5930 * Transmit a beacon frame at SWBA. Dynamic updates 5931 * to the frame contents are done as needed. 5932 */ 5933static void 5934ath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap) 5935{ 5936 struct ath_hal *ah = sc->sc_ah; 5937 struct ath_buf *bf; 5938 int otherant; 5939 5940 /* 5941 * Check if the previous beacon has gone out. If 5942 * not don't try to post another, skip this period 5943 * and wait for the next. Missed beacons indicate 5944 * a problem and should not occur. If we miss too 5945 * many consecutive beacons reset the device. 5946 */ 5947 if (ath_hal_numtxpending(ah, sc->sc_bhalq) != 0) { 5948 sc->sc_bmisscount++; 5949 DPRINTF(sc, ATH_DEBUG_BEACON, 5950 "%s: missed %u consecutive beacons\n", 5951 __func__, sc->sc_bmisscount); 5952 if (sc->sc_bmisscount >= ath_bstuck_threshold) 5953 taskqueue_enqueue(sc->sc_tq, &sc->sc_bstucktask); 5954 return; 5955 } 5956 if (sc->sc_bmisscount != 0) { 5957 DPRINTF(sc, ATH_DEBUG_BEACON, 5958 "%s: resume beacon xmit after %u misses\n", 5959 __func__, sc->sc_bmisscount); 5960 sc->sc_bmisscount = 0; 5961 } 5962 5963 /* 5964 * Check recent per-antenna transmit statistics and flip 5965 * the default antenna if noticeably more frames went out 5966 * on the non-default antenna. 5967 * XXX assumes 2 anntenae 5968 */ 5969 if (!sc->sc_diversity) { 5970 otherant = sc->sc_defant & 1 ? 2 : 1; 5971 if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] + 2) 5972 ath_setdefantenna(sc, otherant); 5973 sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0; 5974 } 5975 5976 bf = ath_beacon_generate(sc, vap); 5977 if (bf != NULL) { 5978 /* 5979 * Stop any current dma and put the new frame on the queue. 5980 * This should never fail since we check above that no frames 5981 * are still pending on the queue. 5982 */ 5983 if (!ath_hal_stoptxdma(ah, sc->sc_bhalq)) { 5984 DPRINTF(sc, ATH_DEBUG_ANY, 5985 "%s: beacon queue %u did not stop?\n", 5986 __func__, sc->sc_bhalq); 5987 /* NB: the HAL still stops DMA, so proceed */ 5988 } 5989 ath_hal_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr); 5990 ath_hal_txstart(ah, sc->sc_bhalq); 5991 5992 sc->sc_stats.ast_be_xmit++; /* XXX per-vap? */ 5993 5994 /* 5995 * Record local TSF for our last send for use 5996 * in arbitrating slot collisions. 5997 */ 5998 /* XXX should take a locked ref to iv_bss */ 5999 vap->iv_bss->ni_tstamp.tsf = ath_hal_gettsf64(ah); 6000 } 6001} 6002#endif /* IEEE80211_SUPPORT_TDMA */ 6003 6004static void | |
6005ath_dfs_tasklet(void *p, int npending) 6006{ 6007 struct ath_softc *sc = (struct ath_softc *) p; 6008 struct ifnet *ifp = sc->sc_ifp; 6009 struct ieee80211com *ic = ifp->if_l2com; 6010 6011 /* 6012 * If previous processing has found a radar event, --- 21 unchanged lines hidden --- | 5646ath_dfs_tasklet(void *p, int npending) 5647{ 5648 struct ath_softc *sc = (struct ath_softc *) p; 5649 struct ifnet *ifp = sc->sc_ifp; 5650 struct ieee80211com *ic = ifp->if_l2com; 5651 5652 /* 5653 * If previous processing has found a radar event, --- 21 unchanged lines hidden --- |