Deleted Added
sdiff udiff text old ( 190526 ) new ( 190571 )
full compact
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 190571 2009-03-30 19:23:49Z sam $");
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
40#include "opt_inet.h"
41#include "opt_ath.h"
42#include "opt_wlan.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/sysctl.h>
47#include <sys/mbuf.h>
48#include <sys/malloc.h>
49#include <sys/lock.h>
50#include <sys/mutex.h>

--- 15 unchanged lines hidden (view full) ---

66#include <net/if_media.h>
67#include <net/if_types.h>
68#include <net/if_arp.h>
69#include <net/ethernet.h>
70#include <net/if_llc.h>
71
72#include <net80211/ieee80211_var.h>
73#include <net80211/ieee80211_regdomain.h>
74#ifdef IEEE80211_SUPPORT_TDMA
75#include <net80211/ieee80211_tdma.h>
76#endif
77
78#include <net/bpf.h>
79
80#ifdef INET
81#include <netinet/in.h>
82#include <netinet/if_ether.h>

--- 126 unchanged lines hidden (view full) ---

209static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
210
211static void ath_sysctlattach(struct ath_softc *);
212static int ath_raw_xmit(struct ieee80211_node *,
213 struct mbuf *, const struct ieee80211_bpf_params *);
214static void ath_bpfattach(struct ath_softc *);
215static void ath_announce(struct ath_softc *);
216
217#ifdef IEEE80211_SUPPORT_TDMA
218static void ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt,
219 u_int32_t bintval);
220static void ath_tdma_bintvalsetup(struct ath_softc *sc,
221 const struct ieee80211_tdma_state *tdma);
222static void ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap);
223static void ath_tdma_update(struct ieee80211_node *ni,
224 const struct ieee80211_tdma_param *tdma, int);
225static void ath_tdma_beacon_send(struct ath_softc *sc,

--- 25 unchanged lines hidden (view full) ---

251#define TDMA_LPF(x, y, len) \
252 ((x != TDMA_DUMMY_MARKER) ? (((x) * ((len)-1) + (y)) / (len)) : (y))
253#define TDMA_SAMPLE(x, y) do { \
254 x = TDMA_LPF((x), TDMA_IN(y), TDMA_LPF_LEN); \
255} while (0)
256#define TDMA_EP_RND(x,mul) \
257 ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
258#define TDMA_AVG(x) TDMA_EP_RND(x, TDMA_EP_MULTIPLIER)
259#endif /* IEEE80211_SUPPORT_TDMA */
260
261SYSCTL_DECL(_hw_ath);
262
263/* XXX validate sysctl values */
264static int ath_longcalinterval = 30; /* long cals every 30 secs */
265SYSCTL_INT(_hw_ath, OID_AUTO, longcal, CTLFLAG_RW, &ath_longcalinterval,
266 0, "long chip calibration interval (secs)");
267static int ath_shortcalinterval = 100; /* short cals every 100 ms */

--- 386 unchanged lines hidden (view full) ---

654 ic->ic_caps |= IEEE80211_C_BURST;
655 sc->sc_hasbmask = ath_hal_hasbssidmask(ah);
656 sc->sc_hastsfadd = ath_hal_hastsfadjust(ah);
657 if (ath_hal_hasfastframes(ah))
658 ic->ic_caps |= IEEE80211_C_FF;
659 wmodes = ath_hal_getwirelessmodes(ah);
660 if (wmodes & (HAL_MODE_108G|HAL_MODE_TURBO))
661 ic->ic_caps |= IEEE80211_C_TURBOP;
662#ifdef IEEE80211_SUPPORT_TDMA
663 if (ath_hal_macversion(ah) > 0x78) {
664 ic->ic_caps |= IEEE80211_C_TDMA; /* capable of TDMA */
665 ic->ic_tdma_update = ath_tdma_update;
666 }
667#endif
668 /*
669 * Indicate we need the 802.11 header padded to a
670 * 32-bit boundary for 4-address and QoS frames.

--- 212 unchanged lines hidden (view full) ---

883 device_printf(sc->sc_dev,
884 "only 1 ibss vap supported\n");
885 goto bad;
886 }
887 ic_opmode = opmode;
888 needbeacon = 1;
889 break;
890 case IEEE80211_M_AHDEMO:
891#ifdef IEEE80211_SUPPORT_TDMA
892 if (flags & IEEE80211_CLONE_TDMA) {
893 needbeacon = 1;
894 flags |= IEEE80211_CLONE_NOBEACONS;
895 }
896 /* fall thru... */
897#endif
898 case IEEE80211_M_MONITOR:
899 if (sc->sc_nvaps != 0 && ic->ic_opmode != opmode) {

--- 108 unchanged lines hidden (view full) ---

1008 switch (ic_opmode) {
1009 case IEEE80211_M_IBSS:
1010 sc->sc_opmode = HAL_M_IBSS;
1011 break;
1012 case IEEE80211_M_STA:
1013 sc->sc_opmode = HAL_M_STA;
1014 break;
1015 case IEEE80211_M_AHDEMO:
1016#ifdef IEEE80211_SUPPORT_TDMA
1017 if (vap->iv_caps & IEEE80211_C_TDMA) {
1018 sc->sc_tdma = 1;
1019 /* NB: disable tsf adjust */
1020 sc->sc_stagbeacons = 0;
1021 }
1022 /*
1023 * NB: adhoc demo mode is a pseudo mode; to the hal it's
1024 * just ap mode.

--- 89 unchanged lines hidden (view full) ---

1114 if (sc->sc_nstavaps == 0 && sc->sc_swbmiss)
1115 sc->sc_swbmiss = 0;
1116 } else if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
1117 reclaim_address(sc, vap->iv_myaddr);
1118 ath_hal_setbssidmask(ah, sc->sc_hwbssidmask);
1119 }
1120 if (vap->iv_opmode != IEEE80211_M_WDS)
1121 sc->sc_nvaps--;
1122#ifdef IEEE80211_SUPPORT_TDMA
1123 /* TDMA operation ceases when the last vap is destroyed */
1124 if (sc->sc_tdma && sc->sc_nvaps == 0) {
1125 sc->sc_tdma = 0;
1126 sc->sc_swbmiss = 0;
1127 }
1128#endif
1129 ATH_UNLOCK(sc);
1130 free(avp, M_80211_VAP);

--- 144 unchanged lines hidden (view full) ---

1275 } else {
1276 if (status & HAL_INT_SWBA) {
1277 /*
1278 * Software beacon alert--time to send a beacon.
1279 * Handle beacon transmission directly; deferring
1280 * this is too slow to meet timing constraints
1281 * under load.
1282 */
1283#ifdef IEEE80211_SUPPORT_TDMA
1284 if (sc->sc_tdma) {
1285 if (sc->sc_tdmaswba == 0) {
1286 struct ieee80211com *ic = ifp->if_l2com;
1287 struct ieee80211vap *vap =
1288 TAILQ_FIRST(&ic->ic_vaps);
1289 ath_tdma_beacon_send(sc, vap);
1290 sc->sc_tdmaswba =
1291 vap->iv_tdma->tdma_bintval;

--- 330 unchanged lines hidden (view full) ---

1622 if_printf(ifp, "%s: unable to start recv logic\n", __func__);
1623 /*
1624 * We may be doing a reset in response to an ioctl
1625 * that changes the channel so update any state that
1626 * might change as a result.
1627 */
1628 ath_chan_change(sc, ic->ic_curchan);
1629 if (sc->sc_beacons) {
1630#ifdef IEEE80211_SUPPORT_TDMA
1631 if (sc->sc_tdma)
1632 ath_tdma_config(sc, NULL);
1633 else
1634#endif
1635 ath_beacon_config(sc, NULL); /* restart beacons */
1636 }
1637 ath_hal_intrset(ah, sc->sc_imask);
1638

--- 2633 unchanged lines hidden (view full) ---

4272 ni = ieee80211_find_rxnode_withkey(ic,
4273 mtod(m, const struct ieee80211_frame_min *),
4274 rs->rs_keyix == HAL_RXKEYIX_INVALID ?
4275 IEEE80211_KEYIX_NONE : rs->rs_keyix);
4276 if (ni != NULL) {
4277 /*
4278 * Sending station is known, dispatch directly.
4279 */
4280#ifdef IEEE80211_SUPPORT_TDMA
4281 sc->sc_tdmars = rs;
4282#endif
4283 type = ieee80211_input(ni, m,
4284 rs->rs_rssi, nf, rs->rs_tstamp);
4285 ieee80211_free_node(ni);
4286 /*
4287 * Arrange to update the last rx timestamp only for
4288 * frames from our ap when operating in station mode.

--- 158 unchanged lines hidden (view full) ---

4447 struct ifnet *ifp = sc->sc_ifp;
4448 struct ieee80211com *ic = ifp->if_l2com;
4449 struct ath_txq *txq = sc->sc_ac2q[ac];
4450 struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
4451 struct ath_hal *ah = sc->sc_ah;
4452 HAL_TXQ_INFO qi;
4453
4454 ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi);
4455#ifdef IEEE80211_SUPPORT_TDMA
4456 if (sc->sc_tdma) {
4457 /*
4458 * AIFS is zero so there's no pre-transmit wait. The
4459 * burst time defines the slot duration and is configured
4460 * via sysctl. The QCU is setup to not do post-xmit
4461 * back off, lockout all lower-priority QCU's, and fire
4462 * off the DMA beacon alert timer which is setup based
4463 * on the slot configuration.

--- 17 unchanged lines hidden (view full) ---

4481 | HAL_TXQ_TXDESCINT_ENABLE
4482 | HAL_TXQ_TXURNINT_ENABLE
4483 ;
4484 qi.tqi_aifs = wmep->wmep_aifsn;
4485 qi.tqi_cwmin = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmin);
4486 qi.tqi_cwmax = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmax);
4487 qi.tqi_readyTime = 0;
4488 qi.tqi_burstTime = ATH_TXOP_TO_US(wmep->wmep_txopLimit);
4489#ifdef IEEE80211_SUPPORT_TDMA
4490 }
4491#endif
4492
4493 DPRINTF(sc, ATH_DEBUG_RESET,
4494 "%s: Q%u qflags 0x%x aifs %u cwmin %u cwmax %u burstTime %u\n",
4495 __func__, txq->axq_qnum, qi.tqi_qflags,
4496 qi.tqi_aifs, qi.tqi_cwmin, qi.tqi_cwmax, qi.tqi_burstTime);
4497

--- 173 unchanged lines hidden (view full) ---

4671 * on a s/w only queue and loaded on to the CAB queue in
4672 * the SWBA handler since frames only go out on DTIM and
4673 * to avoid possible races.
4674 */
4675 ATH_TXQ_LOCK(txq);
4676 KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0,
4677 ("busy status 0x%x", bf->bf_flags));
4678 if (txq->axq_qnum != ATH_TXQ_SWQ) {
4679#ifdef IEEE80211_SUPPORT_TDMA
4680 int qbusy;
4681
4682 ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
4683 qbusy = ath_hal_txqenabled(ah, txq->axq_qnum);
4684 if (txq->axq_link == NULL) {
4685 /*
4686 * Be careful writing the address to TXDP. If
4687 * the tx q is enabled then this write will be

--- 53 unchanged lines hidden (view full) ---

4741 txq->axq_depth);
4742 } else {
4743 *txq->axq_link = bf->bf_daddr;
4744 DPRINTF(sc, ATH_DEBUG_XMIT,
4745 "%s: link[%u](%p)=%p (%p) depth %d\n", __func__,
4746 txq->axq_qnum, txq->axq_link,
4747 (caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth);
4748 }
4749#endif /* IEEE80211_SUPPORT_TDMA */
4750 txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
4751 ath_hal_txstart(ah, txq->axq_qnum);
4752 } else {
4753 if (txq->axq_link != NULL) {
4754 struct ath_buf *last = ATH_TXQ_LAST(txq);
4755 struct ieee80211_frame *wh;
4756
4757 /* mark previous frame */

--- 218 unchanged lines hidden (view full) ---

4976 } else if (pktlen > vap->iv_rtsthreshold &&
4977 (ni->ni_ath_flags & IEEE80211_NODE_FF) == 0) {
4978 flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */
4979 cix = rt->info[rix].controlRate;
4980 sc->sc_stats.ast_tx_rts++;
4981 }
4982 if (flags & HAL_TXDESC_NOACK) /* NB: avoid double counting */
4983 sc->sc_stats.ast_tx_noack++;
4984#ifdef IEEE80211_SUPPORT_TDMA
4985 if (sc->sc_tdma && (flags & HAL_TXDESC_NOACK) == 0) {
4986 DPRINTF(sc, ATH_DEBUG_TDMA,
4987 "%s: discard frame, ACK required w/ TDMA\n", __func__);
4988 sc->sc_stats.ast_tdma_ack++;
4989 ath_freetx(m0);
4990 return EIO;
4991 }
4992#endif

--- 225 unchanged lines hidden (view full) ---

5218 ath_printtxbuf(sc, bf, txq->axq_qnum, 0,
5219 status == HAL_OK);
5220#endif
5221 if (status == HAL_EINPROGRESS) {
5222 ATH_TXQ_UNLOCK(txq);
5223 break;
5224 }
5225 ATH_TXQ_REMOVE_HEAD(txq, bf_list);
5226#ifdef IEEE80211_SUPPORT_TDMA
5227 if (txq->axq_depth > 0) {
5228 /*
5229 * More frames follow. Mark the buffer busy
5230 * so it's not re-used while the hardware may
5231 * still re-read the link field in the descriptor.
5232 */
5233 bf->bf_flags |= ATH_BUF_BUSY;
5234 } else

--- 694 unchanged lines hidden (view full) ---

5929
5930 DPRINTF(sc, ATH_DEBUG_STATE,
5931 "%s(RUN): iv_flags 0x%08x bintvl %d bssid %s "
5932 "capinfo 0x%04x chan %d\n", __func__,
5933 vap->iv_flags, ni->ni_intval, ether_sprintf(ni->ni_bssid),
5934 ni->ni_capinfo, ieee80211_chan2ieee(ic, ic->ic_curchan));
5935
5936 switch (vap->iv_opmode) {
5937#ifdef IEEE80211_SUPPORT_TDMA
5938 case IEEE80211_M_AHDEMO:
5939 if ((vap->iv_caps & IEEE80211_C_TDMA) == 0)
5940 break;
5941 /* fall thru... */
5942#endif
5943 case IEEE80211_M_HOSTAP:
5944 case IEEE80211_M_IBSS:
5945 /*

--- 17 unchanged lines hidden (view full) ---

5963 * starting an ibss/bss so there's no need to delay;
5964 * if this is the first vap moving to RUN state, then
5965 * beacon state needs to be [re]configured.
5966 */
5967 if (vap->iv_opmode == IEEE80211_M_IBSS &&
5968 ni->ni_tstamp.tsf != 0) {
5969 sc->sc_syncbeacon = 1;
5970 } else if (!sc->sc_beacons) {
5971#ifdef IEEE80211_SUPPORT_TDMA
5972 if (vap->iv_caps & IEEE80211_C_TDMA)
5973 ath_tdma_config(sc, vap);
5974 else
5975#endif
5976 ath_beacon_config(sc, vap);
5977 sc->sc_beacons = 1;
5978 }
5979 break;

--- 51 unchanged lines hidden (view full) ---

6031 */
6032 if (!ath_isanyrunningvaps(vap)) {
6033 sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
6034 /* disable interrupts */
6035 ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL);
6036 taskqueue_block(sc->sc_tq);
6037 sc->sc_beacons = 0;
6038 }
6039#ifdef IEEE80211_SUPPORT_TDMA
6040 ath_hal_setcca(ah, AH_TRUE);
6041#endif
6042 }
6043bad:
6044 return error;
6045}
6046
6047/*

--- 491 unchanged lines hidden (view full) ---

6539 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
6540 break;
6541 case SIOCGATHSTATS:
6542 /* NB: embed these numbers to get a consistent view */
6543 sc->sc_stats.ast_tx_packets = ifp->if_opackets;
6544 sc->sc_stats.ast_rx_packets = ifp->if_ipackets;
6545 sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi);
6546 sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi);
6547#ifdef IEEE80211_SUPPORT_TDMA
6548 sc->sc_stats.ast_tdma_tsfadjp = TDMA_AVG(sc->sc_avgtsfdeltap);
6549 sc->sc_stats.ast_tdma_tsfadjm = TDMA_AVG(sc->sc_avgtsfdeltam);
6550#endif
6551 rt = sc->sc_currates;
6552 /* XXX HT rates */
6553 sc->sc_stats.ast_tx_rate =
6554 rt->info[sc->sc_txrix].dot11Rate &~ IEEE80211_RATE_BASIC;
6555 return copyout(&sc->sc_stats,

--- 273 unchanged lines hidden (view full) ---

6829
6830 intmit = ath_hal_getintmit(sc->sc_ah);
6831 error = sysctl_handle_int(oidp, &intmit, 0, req);
6832 if (error || !req->newptr)
6833 return error;
6834 return !ath_hal_setintmit(sc->sc_ah, intmit) ? EINVAL : 0;
6835}
6836
6837#ifdef IEEE80211_SUPPORT_TDMA
6838static int
6839ath_sysctl_setcca(SYSCTL_HANDLER_ARGS)
6840{
6841 struct ath_softc *sc = arg1;
6842 int setcca, error;
6843
6844 setcca = sc->sc_setcca;
6845 error = sysctl_handle_int(oidp, &setcca, 0, req);
6846 if (error || !req->newptr)
6847 return error;
6848 sc->sc_setcca = (setcca != 0);
6849 return 0;
6850}
6851#endif /* IEEE80211_SUPPORT_TDMA */
6852
6853static void
6854ath_sysctlattach(struct ath_softc *sc)
6855{
6856 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
6857 struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
6858 struct ath_hal *ah = sc->sc_ah;
6859

--- 82 unchanged lines hidden (view full) ---

6942 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
6943 "intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
6944 ath_sysctl_intmit, "I", "interference mitigation");
6945 }
6946 sc->sc_monpass = HAL_RXERR_DECRYPT | HAL_RXERR_MIC;
6947 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
6948 "monpass", CTLFLAG_RW, &sc->sc_monpass, 0,
6949 "mask of error frames to pass when monitoring");
6950#ifdef IEEE80211_SUPPORT_TDMA
6951 if (ath_hal_macversion(ah) > 0x78) {
6952 sc->sc_tdmadbaprep = 2;
6953 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
6954 "dbaprep", CTLFLAG_RW, &sc->sc_tdmadbaprep, 0,
6955 "TDMA DBA preparation time");
6956 sc->sc_tdmaswbaprep = 10;
6957 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
6958 "swbaprep", CTLFLAG_RW, &sc->sc_tdmaswbaprep, 0,

--- 322 unchanged lines hidden (view full) ---

7281 if_printf(ifp, "Use hw queue %u for beacons\n", sc->sc_bhalq);
7282 }
7283 if (ath_rxbuf != ATH_RXBUF)
7284 if_printf(ifp, "using %u rx buffers\n", ath_rxbuf);
7285 if (ath_txbuf != ATH_TXBUF)
7286 if_printf(ifp, "using %u tx buffers\n", ath_txbuf);
7287}
7288
7289#ifdef IEEE80211_SUPPORT_TDMA
7290static __inline uint32_t
7291ath_hal_getnexttbtt(struct ath_hal *ah)
7292{
7293#define AR_TIMER0 0x8028
7294 return OS_REG_READ(ah, AR_TIMER0);
7295}
7296
7297static __inline void

--- 343 unchanged lines hidden (view full) ---

7641
7642 /*
7643 * Record local TSF for our last send for use
7644 * in arbitrating slot collisions.
7645 */
7646 vap->iv_bss->ni_tstamp.tsf = ath_hal_gettsf64(ah);
7647 }
7648}
7649#endif /* IEEE80211_SUPPORT_TDMA */