1116743Ssam/*-
2186904Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3116743Ssam * All rights reserved.
4116743Ssam *
5116743Ssam * Redistribution and use in source and binary forms, with or without
6116743Ssam * modification, are permitted provided that the following conditions
7116743Ssam * are met:
8116743Ssam * 1. Redistributions of source code must retain the above copyright
9116743Ssam *    notice, this list of conditions and the following disclaimer,
10116743Ssam *    without modification.
11116743Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12116743Ssam *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13116743Ssam *    redistribution must be conditioned upon including a substantially
14116743Ssam *    similar Disclaimer requirement for further binary redistribution.
15116743Ssam *
16116743Ssam * NO WARRANTY
17116743Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18116743Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19116743Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20116743Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21116743Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22116743Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23116743Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24116743Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25116743Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26116743Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27116743Ssam * THE POSSIBILITY OF SUCH DAMAGES.
28116743Ssam */
29116743Ssam
30116743Ssam#include <sys/cdefs.h>
31116743Ssam__FBSDID("$FreeBSD$");
32116743Ssam
33116743Ssam/*
34116743Ssam * Driver for the Atheros Wireless LAN controller.
35117055Ssam *
36117055Ssam * This software is derived from work of Atsushi Onoe; his contribution
37117055Ssam * is greatly appreciated.
38116743Ssam */
39116743Ssam
40116743Ssam#include "opt_inet.h"
41157438Ssam#include "opt_ath.h"
42190571Ssam#include "opt_wlan.h"
43116743Ssam
44116743Ssam#include <sys/param.h>
45204100Sdeischen#include <sys/systm.h>
46116743Ssam#include <sys/sysctl.h>
47204100Sdeischen#include <sys/mbuf.h>
48116743Ssam#include <sys/malloc.h>
49116743Ssam#include <sys/lock.h>
50116743Ssam#include <sys/mutex.h>
51116743Ssam#include <sys/kernel.h>
52116743Ssam#include <sys/socket.h>
53116743Ssam#include <sys/sockio.h>
54116743Ssam#include <sys/errno.h>
55116743Ssam#include <sys/callout.h>
56116743Ssam#include <sys/bus.h>
57116743Ssam#include <sys/endian.h>
58155491Ssam#include <sys/kthread.h>
59155491Ssam#include <sys/taskqueue.h>
60188557Ssam#include <sys/priv.h>
61220185Sadrian#include <sys/module.h>
62116743Ssam
63116743Ssam#include <machine/bus.h>
64204100Sdeischen
65116743Ssam#include <net/if.h>
66116743Ssam#include <net/if_dl.h>
67116743Ssam#include <net/if_media.h>
68147256Sbrooks#include <net/if_types.h>
69116743Ssam#include <net/if_arp.h>
70116743Ssam#include <net/ethernet.h>
71116743Ssam#include <net/if_llc.h>
72116743Ssam
73116743Ssam#include <net80211/ieee80211_var.h>
74187831Ssam#include <net80211/ieee80211_regdomain.h>
75190579Ssam#ifdef IEEE80211_SUPPORT_SUPERG
76190579Ssam#include <net80211/ieee80211_superg.h>
77190579Ssam#endif
78190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
79186904Ssam#include <net80211/ieee80211_tdma.h>
80186904Ssam#endif
81116743Ssam
82116743Ssam#include <net/bpf.h>
83116743Ssam
84116743Ssam#ifdef INET
85204100Sdeischen#include <netinet/in.h>
86116743Ssam#include <netinet/if_ether.h>
87116743Ssam#endif
88116743Ssam
89116743Ssam#include <dev/ath/if_athvar.h>
90185522Ssam#include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
91217618Sadrian#include <dev/ath/ath_hal/ah_diagcodes.h>
92116743Ssam
93218058Sadrian#include <dev/ath/if_ath_debug.h>
94218065Sadrian#include <dev/ath/if_ath_misc.h>
95218065Sadrian#include <dev/ath/if_ath_tx.h>
96219180Sadrian#include <dev/ath/if_ath_sysctl.h>
97219185Sadrian#include <dev/ath/if_ath_keycache.h>
98222585Sadrian#include <dev/ath/if_athdfs.h>
99218058Sadrian
100155486Ssam#ifdef ATH_TX99_DIAG
101155486Ssam#include <dev/ath/ath_tx99/ath_tx99.h>
102155486Ssam#endif
103155486Ssam
104222585Sadrian
105178354Ssam/*
106178354Ssam * ATH_BCBUF determines the number of vap's that can transmit
107178354Ssam * beacons and also (currently) the number of vap's that can
108178354Ssam * have unique mac addresses/bssid.  When staggering beacons
109178354Ssam * 4 is probably a good max as otherwise the beacons become
110178354Ssam * very closely spaced and there is limited time for cab q traffic
111178354Ssam * to go out.  You can burst beacons instead but that is not good
112178354Ssam * for stations in power save and at some point you really want
113178354Ssam * another radio (and channel).
114178354Ssam *
115178354Ssam * The limit on the number of mac addresses is tied to our use of
116178354Ssam * the U/L bit and tracking addresses in a byte; it would be
117178354Ssam * worthwhile to allow more for applications like proxy sta.
118178354Ssam */
119178354SsamCTASSERT(ATH_BCBUF <= 8);
120178354Ssam
121178354Ssamstatic struct ieee80211vap *ath_vap_create(struct ieee80211com *,
122234753Sdim		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
123234753Sdim		    const uint8_t [IEEE80211_ADDR_LEN],
124234753Sdim		    const uint8_t [IEEE80211_ADDR_LEN]);
125178354Ssamstatic void	ath_vap_delete(struct ieee80211vap *);
126116743Ssamstatic void	ath_init(void *);
127138570Ssamstatic void	ath_stop_locked(struct ifnet *);
128116743Ssamstatic void	ath_stop(struct ifnet *);
129116743Ssamstatic void	ath_start(struct ifnet *);
130178354Ssamstatic int	ath_reset_vap(struct ieee80211vap *, u_long);
131116743Ssamstatic int	ath_media_change(struct ifnet *);
132189605Ssamstatic void	ath_watchdog(void *);
133116743Ssamstatic int	ath_ioctl(struct ifnet *, u_long, caddr_t);
134116743Ssamstatic void	ath_fatal_proc(void *, int);
135178354Ssamstatic void	ath_bmiss_vap(struct ieee80211vap *);
136116743Ssamstatic void	ath_bmiss_proc(void *, int);
137178354Ssamstatic void	ath_key_update_begin(struct ieee80211vap *);
138178354Ssamstatic void	ath_key_update_end(struct ieee80211vap *);
139178354Ssamstatic void	ath_update_mcast(struct ifnet *);
140178354Ssamstatic void	ath_update_promisc(struct ifnet *);
141116743Ssamstatic void	ath_mode_init(struct ath_softc *);
142138570Ssamstatic void	ath_setslottime(struct ath_softc *);
143138570Ssamstatic void	ath_updateslot(struct ifnet *);
144140433Ssamstatic int	ath_beaconq_setup(struct ath_hal *);
145116743Ssamstatic int	ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *);
146178354Ssamstatic void	ath_beacon_update(struct ieee80211vap *, int item);
147138570Ssamstatic void	ath_beacon_setup(struct ath_softc *, struct ath_buf *);
148116743Ssamstatic void	ath_beacon_proc(void *, int);
149178354Ssamstatic struct ath_buf *ath_beacon_generate(struct ath_softc *,
150178354Ssam			struct ieee80211vap *);
151138570Ssamstatic void	ath_bstuck_proc(void *, int);
152178354Ssamstatic void	ath_beacon_return(struct ath_softc *, struct ath_buf *);
153116743Ssamstatic void	ath_beacon_free(struct ath_softc *);
154178354Ssamstatic void	ath_beacon_config(struct ath_softc *, struct ieee80211vap *);
155138570Ssamstatic void	ath_descdma_cleanup(struct ath_softc *sc,
156138570Ssam			struct ath_descdma *, ath_bufhead *);
157116743Ssamstatic int	ath_desc_alloc(struct ath_softc *);
158116743Ssamstatic void	ath_desc_free(struct ath_softc *);
159179643Ssamstatic struct ieee80211_node *ath_node_alloc(struct ieee80211vap *,
160179643Ssam			const uint8_t [IEEE80211_ADDR_LEN]);
161138570Ssamstatic void	ath_node_free(struct ieee80211_node *);
162170530Ssamstatic void	ath_node_getsignal(const struct ieee80211_node *,
163170530Ssam			int8_t *, int8_t *);
164116743Ssamstatic int	ath_rxbuf_init(struct ath_softc *, struct ath_buf *);
165178354Ssamstatic void	ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
166192468Ssam			int subtype, int rssi, int nf);
167138570Ssamstatic void	ath_setdefantenna(struct ath_softc *, u_int);
168116743Ssamstatic void	ath_rx_proc(void *, int);
169159938Ssamstatic void	ath_txq_init(struct ath_softc *sc, struct ath_txq *, int);
170138570Ssamstatic struct ath_txq *ath_txq_setup(struct ath_softc*, int qtype, int subtype);
171138570Ssamstatic int	ath_tx_setup(struct ath_softc *, int, int);
172138570Ssamstatic int	ath_wme_update(struct ieee80211com *);
173138570Ssamstatic void	ath_tx_cleanupq(struct ath_softc *, struct ath_txq *);
174138570Ssamstatic void	ath_tx_cleanup(struct ath_softc *);
175138570Ssamstatic void	ath_tx_proc_q0(void *, int);
176138570Ssamstatic void	ath_tx_proc_q0123(void *, int);
177116743Ssamstatic void	ath_tx_proc(void *, int);
178178354Ssamstatic void	ath_tx_draintxq(struct ath_softc *, struct ath_txq *);
179116743Ssamstatic int	ath_chan_set(struct ath_softc *, struct ieee80211_channel *);
180116743Ssamstatic void	ath_draintxq(struct ath_softc *);
181116743Ssamstatic void	ath_stoprecv(struct ath_softc *);
182116743Ssamstatic int	ath_startrecv(struct ath_softc *);
183138570Ssamstatic void	ath_chan_change(struct ath_softc *, struct ieee80211_channel *);
184170530Ssamstatic void	ath_scan_start(struct ieee80211com *);
185170530Ssamstatic void	ath_scan_end(struct ieee80211com *);
186170530Ssamstatic void	ath_set_channel(struct ieee80211com *);
187116743Ssamstatic void	ath_calibrate(void *);
188178354Ssamstatic int	ath_newstate(struct ieee80211vap *, enum ieee80211_state, int);
189147057Ssamstatic void	ath_setup_stationkey(struct ieee80211_node *);
190148307Ssamstatic void	ath_newassoc(struct ieee80211_node *, int);
191178354Ssamstatic int	ath_setregdomain(struct ieee80211com *,
192178354Ssam		    struct ieee80211_regdomain *, int,
193178354Ssam		    struct ieee80211_channel []);
194187800Ssamstatic void	ath_getradiocaps(struct ieee80211com *, int, int *,
195178354Ssam		    struct ieee80211_channel []);
196178354Ssamstatic int	ath_getchannels(struct ath_softc *);
197140432Ssamstatic void	ath_led_event(struct ath_softc *, int);
198116743Ssam
199138570Ssamstatic int	ath_rate_setup(struct ath_softc *, u_int mode);
200116743Ssamstatic void	ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
201116743Ssam
202138570Ssamstatic void	ath_announce(struct ath_softc *);
203138570Ssam
204222585Sadrianstatic void	ath_dfs_tasklet(void *, int);
205222585Sadrian
206190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
207186904Ssamstatic void	ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt,
208186904Ssam		    u_int32_t bintval);
209186904Ssamstatic void	ath_tdma_bintvalsetup(struct ath_softc *sc,
210186904Ssam		    const struct ieee80211_tdma_state *tdma);
211186904Ssamstatic void	ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap);
212186904Ssamstatic void	ath_tdma_update(struct ieee80211_node *ni,
213189980Ssam		    const struct ieee80211_tdma_param *tdma, int);
214186904Ssamstatic void	ath_tdma_beacon_send(struct ath_softc *sc,
215186904Ssam		    struct ieee80211vap *vap);
216186904Ssam
217186904Ssam#define	TDMA_EP_MULTIPLIER	(1<<10) /* pow2 to optimize out * and / */
218186904Ssam#define	TDMA_LPF_LEN		6
219186904Ssam#define	TDMA_DUMMY_MARKER	0x127
220186904Ssam#define	TDMA_EP_MUL(x, mul)	((x) * (mul))
221186904Ssam#define	TDMA_IN(x)		(TDMA_EP_MUL((x), TDMA_EP_MULTIPLIER))
222186904Ssam#define	TDMA_LPF(x, y, len) \
223186904Ssam    ((x != TDMA_DUMMY_MARKER) ? (((x) * ((len)-1) + (y)) / (len)) : (y))
224186904Ssam#define	TDMA_SAMPLE(x, y) do {					\
225186904Ssam	x = TDMA_LPF((x), TDMA_IN(y), TDMA_LPF_LEN);		\
226186904Ssam} while (0)
227186904Ssam#define	TDMA_EP_RND(x,mul) \
228186904Ssam	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
229186904Ssam#define	TDMA_AVG(x)		TDMA_EP_RND(x, TDMA_EP_MULTIPLIER)
230190571Ssam#endif /* IEEE80211_SUPPORT_TDMA */
231186904Ssam
232116743SsamSYSCTL_DECL(_hw_ath);
233116743Ssam
234116743Ssam/* XXX validate sysctl values */
235185744Ssamstatic	int ath_longcalinterval = 30;		/* long cals every 30 secs */
236185744SsamSYSCTL_INT(_hw_ath, OID_AUTO, longcal, CTLFLAG_RW, &ath_longcalinterval,
237185744Ssam	    0, "long chip calibration interval (secs)");
238185744Ssamstatic	int ath_shortcalinterval = 100;		/* short cals every 100 ms */
239185744SsamSYSCTL_INT(_hw_ath, OID_AUTO, shortcal, CTLFLAG_RW, &ath_shortcalinterval,
240185744Ssam	    0, "short chip calibration interval (msecs)");
241185744Ssamstatic	int ath_resetcalinterval = 20*60;	/* reset cal state 20 mins */
242185744SsamSYSCTL_INT(_hw_ath, OID_AUTO, resetcal, CTLFLAG_RW, &ath_resetcalinterval,
243185744Ssam	    0, "reset chip calibration results (secs)");
244217684Sadrianstatic	int ath_anicalinterval = 100;		/* ANI calibration - 100 msec */
245217684SadrianSYSCTL_INT(_hw_ath, OID_AUTO, anical, CTLFLAG_RW, &ath_anicalinterval,
246217684Sadrian	    0, "ANI calibration (msecs)");
247116743Ssam
248155481Ssamstatic	int ath_rxbuf = ATH_RXBUF;		/* # rx buffers to allocate */
249165571SsamSYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf,
250155481Ssam	    0, "rx buffers allocated");
251155481SsamTUNABLE_INT("hw.ath.rxbuf", &ath_rxbuf);
252155481Ssamstatic	int ath_txbuf = ATH_TXBUF;		/* # tx buffers to allocate */
253165571SsamSYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RW, &ath_txbuf,
254155481Ssam	    0, "tx buffers allocated");
255155481SsamTUNABLE_INT("hw.ath.txbuf", &ath_txbuf);
256155481Ssam
257188446Ssamstatic	int ath_bstuck_threshold = 4;		/* max missed beacons */
258188446SsamSYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold,
259188446Ssam	    0, "max missed beacon xmits before chip reset");
260188446Ssam
261249132Smavstatic MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers");
262138570Ssam
263218488Sadrian#define	HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20)
264218488Sadrian#define	HAL_MODE_HT40 \
265218488Sadrian	(HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \
266218488Sadrian	HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS)
267116743Ssamint
268116743Ssamath_attach(u_int16_t devid, struct ath_softc *sc)
269116743Ssam{
270147256Sbrooks	struct ifnet *ifp;
271178354Ssam	struct ieee80211com *ic;
272147256Sbrooks	struct ath_hal *ah = NULL;
273116743Ssam	HAL_STATUS status;
274138570Ssam	int error = 0, i;
275184369Ssam	u_int wmodes;
276190526Ssam	uint8_t macaddr[IEEE80211_ADDR_LEN];
277116743Ssam
278138570Ssam	DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
279116743Ssam
280178354Ssam	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
281147256Sbrooks	if (ifp == NULL) {
282147256Sbrooks		device_printf(sc->sc_dev, "can not if_alloc()\n");
283147256Sbrooks		error = ENOSPC;
284147256Sbrooks		goto bad;
285147256Sbrooks	}
286178354Ssam	ic = ifp->if_l2com;
287147256Sbrooks
288116743Ssam	/* set these up early for if_printf use */
289121816Sbrooks	if_initname(ifp, device_get_name(sc->sc_dev),
290138570Ssam		device_get_unit(sc->sc_dev));
291116743Ssam
292217624Sadrian	ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh, sc->sc_eepromdata, &status);
293116743Ssam	if (ah == NULL) {
294116743Ssam		if_printf(ifp, "unable to attach hardware; HAL status %u\n",
295116743Ssam			status);
296116743Ssam		error = ENXIO;
297116743Ssam		goto bad;
298116743Ssam	}
299116743Ssam	sc->sc_ah = ah;
300118884Ssam	sc->sc_invalid = 0;	/* ready to go, enable interrupt handling */
301184353Ssam#ifdef	ATH_DEBUG
302184353Ssam	sc->sc_debug = ath_debug;
303184353Ssam#endif
304116743Ssam
305116743Ssam	/*
306138570Ssam	 * Check if the MAC has multi-rate retry support.
307138570Ssam	 * We do this by trying to setup a fake extended
308138570Ssam	 * descriptor.  MAC's that don't have support will
309138570Ssam	 * return false w/o doing anything.  MAC's that do
310138570Ssam	 * support it will return true w/o doing anything.
311138570Ssam	 */
312138570Ssam	sc->sc_mrretry = ath_hal_setupxtxdesc(ah, NULL, 0,0, 0,0, 0,0);
313138570Ssam
314138570Ssam	/*
315138570Ssam	 * Check if the device has hardware counters for PHY
316138570Ssam	 * errors.  If so we need to enable the MIB interrupt
317138570Ssam	 * so we can act on stat triggers.
318138570Ssam	 */
319138570Ssam	if (ath_hal_hwphycounters(ah))
320138570Ssam		sc->sc_needmib = 1;
321138570Ssam
322138570Ssam	/*
323138570Ssam	 * Get the hardware key cache size.
324138570Ssam	 */
325138570Ssam	sc->sc_keymax = ath_hal_keycachesize(ah);
326147057Ssam	if (sc->sc_keymax > ATH_KEYMAX) {
327147057Ssam		if_printf(ifp, "Warning, using only %u of %u key cache slots\n",
328147057Ssam			ATH_KEYMAX, sc->sc_keymax);
329147057Ssam		sc->sc_keymax = ATH_KEYMAX;
330138570Ssam	}
331138570Ssam	/*
332138570Ssam	 * Reset the key cache since some parts do not
333138570Ssam	 * reset the contents on initial power up.
334138570Ssam	 */
335138570Ssam	for (i = 0; i < sc->sc_keymax; i++)
336138570Ssam		ath_hal_keyreset(ah, i);
337138570Ssam
338138570Ssam	/*
339178354Ssam	 * Collect the default channel list.
340116743Ssam	 */
341178354Ssam	error = ath_getchannels(sc);
342116743Ssam	if (error != 0)
343116743Ssam		goto bad;
344116743Ssam
345116743Ssam	/*
346116743Ssam	 * Setup rate tables for all potential media types.
347116743Ssam	 */
348116743Ssam	ath_rate_setup(sc, IEEE80211_MODE_11A);
349116743Ssam	ath_rate_setup(sc, IEEE80211_MODE_11B);
350116743Ssam	ath_rate_setup(sc, IEEE80211_MODE_11G);
351138570Ssam	ath_rate_setup(sc, IEEE80211_MODE_TURBO_A);
352138570Ssam	ath_rate_setup(sc, IEEE80211_MODE_TURBO_G);
353170530Ssam	ath_rate_setup(sc, IEEE80211_MODE_STURBO_A);
354170530Ssam	ath_rate_setup(sc, IEEE80211_MODE_11NA);
355170530Ssam	ath_rate_setup(sc, IEEE80211_MODE_11NG);
356166013Ssam	ath_rate_setup(sc, IEEE80211_MODE_HALF);
357166013Ssam	ath_rate_setup(sc, IEEE80211_MODE_QUARTER);
358165571Ssam
359138570Ssam	/* NB: setup here so ath_rate_update is happy */
360138570Ssam	ath_setcurmode(sc, IEEE80211_MODE_11A);
361116743Ssam
362138570Ssam	/*
363138570Ssam	 * Allocate tx+rx descriptors and populate the lists.
364138570Ssam	 */
365116743Ssam	error = ath_desc_alloc(sc);
366116743Ssam	if (error != 0) {
367116743Ssam		if_printf(ifp, "failed to allocate descriptors: %d\n", error);
368116743Ssam		goto bad;
369116743Ssam	}
370189605Ssam	callout_init_mtx(&sc->sc_cal_ch, &sc->sc_mtx, 0);
371189605Ssam	callout_init_mtx(&sc->sc_wd_ch, &sc->sc_mtx, 0);
372116743Ssam
373121100Ssam	ATH_TXBUF_LOCK_INIT(sc);
374116743Ssam
375155491Ssam	sc->sc_tq = taskqueue_create("ath_taskq", M_NOWAIT,
376155491Ssam		taskqueue_thread_enqueue, &sc->sc_tq);
377155491Ssam	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
378155491Ssam		"%s taskq", ifp->if_xname);
379155491Ssam
380116743Ssam	TASK_INIT(&sc->sc_rxtask, 0, ath_rx_proc, sc);
381116743Ssam	TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc);
382155515Ssam	TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc);
383116743Ssam
384116743Ssam	/*
385138570Ssam	 * Allocate hardware transmit queues: one queue for
386138570Ssam	 * beacon frames and one data queue for each QoS
387204100Sdeischen	 * priority.  Note that the hal handles resetting
388138570Ssam	 * these queues at the needed time.
389138570Ssam	 *
390138570Ssam	 * XXX PS-Poll
391116743Ssam	 */
392140433Ssam	sc->sc_bhalq = ath_beaconq_setup(ah);
393116743Ssam	if (sc->sc_bhalq == (u_int) -1) {
394116743Ssam		if_printf(ifp, "unable to setup a beacon xmit queue!\n");
395138570Ssam		error = EIO;
396127777Ssam		goto bad2;
397116743Ssam	}
398138570Ssam	sc->sc_cabq = ath_txq_setup(sc, HAL_TX_QUEUE_CAB, 0);
399138570Ssam	if (sc->sc_cabq == NULL) {
400138570Ssam		if_printf(ifp, "unable to setup CAB xmit queue!\n");
401138570Ssam		error = EIO;
402138570Ssam		goto bad2;
403138570Ssam	}
404138570Ssam	/* NB: insure BK queue is the lowest priority h/w queue */
405138570Ssam	if (!ath_tx_setup(sc, WME_AC_BK, HAL_WME_AC_BK)) {
406138570Ssam		if_printf(ifp, "unable to setup xmit queue for %s traffic!\n",
407138570Ssam			ieee80211_wme_acnames[WME_AC_BK]);
408138570Ssam		error = EIO;
409138570Ssam		goto bad2;
410138570Ssam	}
411138570Ssam	if (!ath_tx_setup(sc, WME_AC_BE, HAL_WME_AC_BE) ||
412138570Ssam	    !ath_tx_setup(sc, WME_AC_VI, HAL_WME_AC_VI) ||
413138570Ssam	    !ath_tx_setup(sc, WME_AC_VO, HAL_WME_AC_VO)) {
414170530Ssam		/*
415138570Ssam		 * Not enough hardware tx queues to properly do WME;
416138570Ssam		 * just punt and assign them all to the same h/w queue.
417138570Ssam		 * We could do a better job of this if, for example,
418138570Ssam		 * we allocate queues when we switch from station to
419138570Ssam		 * AP mode.
420138570Ssam		 */
421138570Ssam		if (sc->sc_ac2q[WME_AC_VI] != NULL)
422138570Ssam			ath_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_VI]);
423138570Ssam		if (sc->sc_ac2q[WME_AC_BE] != NULL)
424138570Ssam			ath_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_BE]);
425138570Ssam		sc->sc_ac2q[WME_AC_BE] = sc->sc_ac2q[WME_AC_BK];
426138570Ssam		sc->sc_ac2q[WME_AC_VI] = sc->sc_ac2q[WME_AC_BK];
427138570Ssam		sc->sc_ac2q[WME_AC_VO] = sc->sc_ac2q[WME_AC_BK];
428138570Ssam	}
429116743Ssam
430170530Ssam	/*
431138570Ssam	 * Special case certain configurations.  Note the
432138570Ssam	 * CAB queue is handled by these specially so don't
433138570Ssam	 * include them when checking the txq setup mask.
434138570Ssam	 */
435138570Ssam	switch (sc->sc_txqsetup &~ (1<<sc->sc_cabq->axq_qnum)) {
436138570Ssam	case 0x01:
437138570Ssam		TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc_q0, sc);
438138570Ssam		break;
439138570Ssam	case 0x0f:
440138570Ssam		TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc_q0123, sc);
441138570Ssam		break;
442138570Ssam	default:
443138570Ssam		TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc, sc);
444138570Ssam		break;
445138570Ssam	}
446138570Ssam
447138570Ssam	/*
448138570Ssam	 * Setup rate control.  Some rate control modules
449138570Ssam	 * call back to change the anntena state so expose
450138570Ssam	 * the necessary entry points.
451138570Ssam	 * XXX maybe belongs in struct ath_ratectrl?
452138570Ssam	 */
453138570Ssam	sc->sc_setdefantenna = ath_setdefantenna;
454138570Ssam	sc->sc_rc = ath_rate_attach(sc);
455138570Ssam	if (sc->sc_rc == NULL) {
456138570Ssam		error = EIO;
457138570Ssam		goto bad2;
458138570Ssam	}
459138570Ssam
460222585Sadrian	/* Attach DFS module */
461222585Sadrian	if (! ath_dfs_attach(sc)) {
462222585Sadrian		device_printf(sc->sc_dev, "%s: unable to attach DFS\n", __func__);
463222585Sadrian		error = EIO;
464222585Sadrian		goto bad2;
465222585Sadrian	}
466222585Sadrian
467222585Sadrian	/* Start DFS processing tasklet */
468222585Sadrian	TASK_INIT(&sc->sc_dfstask, 0, ath_dfs_tasklet, sc);
469222585Sadrian
470140432Ssam	sc->sc_blinking = 0;
471138570Ssam	sc->sc_ledstate = 1;
472140432Ssam	sc->sc_ledon = 0;			/* low true */
473140432Ssam	sc->sc_ledidle = (2700*hz)/1000;	/* 2.7sec */
474140432Ssam	callout_init(&sc->sc_ledtimer, CALLOUT_MPSAFE);
475138570Ssam	/*
476138570Ssam	 * Auto-enable soft led processing for IBM cards and for
477138570Ssam	 * 5211 minipci cards.  Users can also manually enable/disable
478138570Ssam	 * support with a sysctl.
479138570Ssam	 */
480138570Ssam	sc->sc_softled = (devid == AR5212_DEVID_IBM || devid == AR5211_DEVID);
481138570Ssam	if (sc->sc_softled) {
482188974Ssam		ath_hal_gpioCfgOutput(ah, sc->sc_ledpin,
483188974Ssam		    HAL_GPIO_MUX_MAC_NETWORK_LED);
484140432Ssam		ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon);
485138570Ssam	}
486138570Ssam
487116743Ssam	ifp->if_softc = sc;
488116743Ssam	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
489116743Ssam	ifp->if_start = ath_start;
490116743Ssam	ifp->if_ioctl = ath_ioctl;
491116743Ssam	ifp->if_init = ath_init;
492207554Ssobomax	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
493207554Ssobomax	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
494132986Smlaier	IFQ_SET_READY(&ifp->if_snd);
495116743Ssam
496138570Ssam	ic->ic_ifp = ifp;
497116743Ssam	/* XXX not right but it's not used anywhere important */
498116743Ssam	ic->ic_phytype = IEEE80211_T_OFDM;
499116743Ssam	ic->ic_opmode = IEEE80211_M_STA;
500138570Ssam	ic->ic_caps =
501178957Ssam		  IEEE80211_C_STA		/* station mode */
502178957Ssam		| IEEE80211_C_IBSS		/* ibss, nee adhoc, mode */
503121175Ssam		| IEEE80211_C_HOSTAP		/* hostap mode */
504121175Ssam		| IEEE80211_C_MONITOR		/* monitor mode */
505155490Ssam		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
506178354Ssam		| IEEE80211_C_WDS		/* 4-address traffic works */
507195618Srpaulo		| IEEE80211_C_MBSS		/* mesh point link mode */
508121175Ssam		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
509138570Ssam		| IEEE80211_C_SHSLOT		/* short slot time supported */
510138570Ssam		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
511170530Ssam		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
512170530Ssam		| IEEE80211_C_TXFRAG		/* handle tx frags */
513223567Sadrian#ifdef	ATH_ENABLE_DFS
514223567Sadrian		| IEEE80211_C_DFS		/* Enable DFS radar detection */
515223567Sadrian#endif
516127776Ssam		;
517138570Ssam	/*
518138570Ssam	 * Query the hal to figure out h/w crypto support.
519138570Ssam	 */
520138570Ssam	if (ath_hal_ciphersupported(ah, HAL_CIPHER_WEP))
521178354Ssam		ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
522138570Ssam	if (ath_hal_ciphersupported(ah, HAL_CIPHER_AES_OCB))
523178354Ssam		ic->ic_cryptocaps |= IEEE80211_CRYPTO_AES_OCB;
524138570Ssam	if (ath_hal_ciphersupported(ah, HAL_CIPHER_AES_CCM))
525178354Ssam		ic->ic_cryptocaps |= IEEE80211_CRYPTO_AES_CCM;
526138570Ssam	if (ath_hal_ciphersupported(ah, HAL_CIPHER_CKIP))
527178354Ssam		ic->ic_cryptocaps |= IEEE80211_CRYPTO_CKIP;
528138570Ssam	if (ath_hal_ciphersupported(ah, HAL_CIPHER_TKIP)) {
529178354Ssam		ic->ic_cryptocaps |= IEEE80211_CRYPTO_TKIP;
530138570Ssam		/*
531138570Ssam		 * Check if h/w does the MIC and/or whether the
532138570Ssam		 * separate key cache entries are required to
533138570Ssam		 * handle both tx+rx MIC keys.
534138570Ssam		 */
535138570Ssam		if (ath_hal_ciphersupported(ah, HAL_CIPHER_MIC))
536178354Ssam			ic->ic_cryptocaps |= IEEE80211_CRYPTO_TKIPMIC;
537162410Ssam		/*
538162410Ssam		 * If the h/w supports storing tx+rx MIC keys
539162410Ssam		 * in one cache slot automatically enable use.
540162410Ssam		 */
541162410Ssam		if (ath_hal_hastkipsplit(ah) ||
542162410Ssam		    !ath_hal_settkipsplit(ah, AH_FALSE))
543138570Ssam			sc->sc_splitmic = 1;
544178354Ssam		/*
545178354Ssam		 * If the h/w can do TKIP MIC together with WME then
546178354Ssam		 * we use it; otherwise we force the MIC to be done
547178354Ssam		 * in software by the net80211 layer.
548178354Ssam		 */
549178354Ssam		if (ath_hal_haswmetkipmic(ah))
550178354Ssam			sc->sc_wmetkipmic = 1;
551138570Ssam	}
552147057Ssam	sc->sc_hasclrkey = ath_hal_ciphersupported(ah, HAL_CIPHER_CLR);
553203683Srpaulo	/*
554203751Srpaulo	 * Check for multicast key search support.
555203683Srpaulo	 */
556203683Srpaulo	if (ath_hal_hasmcastkeysearch(sc->sc_ah) &&
557203683Srpaulo	    !ath_hal_getmcastkeysearch(sc->sc_ah)) {
558203683Srpaulo		ath_hal_setmcastkeysearch(sc->sc_ah, 1);
559203683Srpaulo	}
560147057Ssam	sc->sc_mcastkey = ath_hal_getmcastkeysearch(ah);
561138570Ssam	/*
562162410Ssam	 * Mark key cache slots associated with global keys
563162410Ssam	 * as in use.  If we knew TKIP was not to be used we
564162410Ssam	 * could leave the +32, +64, and +32+64 slots free.
565162410Ssam	 */
566162410Ssam	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
567162410Ssam		setbit(sc->sc_keymap, i);
568162410Ssam		setbit(sc->sc_keymap, i+64);
569162410Ssam		if (sc->sc_splitmic) {
570162410Ssam			setbit(sc->sc_keymap, i+32);
571162410Ssam			setbit(sc->sc_keymap, i+32+64);
572162410Ssam		}
573162410Ssam	}
574162410Ssam	/*
575138570Ssam	 * TPC support can be done either with a global cap or
576138570Ssam	 * per-packet support.  The latter is not available on
577138570Ssam	 * all parts.  We're a bit pedantic here as all parts
578138570Ssam	 * support a global cap.
579138570Ssam	 */
580148362Ssam	if (ath_hal_hastpc(ah) || ath_hal_hastxpowlimit(ah))
581138570Ssam		ic->ic_caps |= IEEE80211_C_TXPMGT;
582116743Ssam
583138570Ssam	/*
584138570Ssam	 * Mark WME capability only if we have sufficient
585138570Ssam	 * hardware queues to do proper priority scheduling.
586138570Ssam	 */
587138570Ssam	if (sc->sc_ac2q[WME_AC_BE] != sc->sc_ac2q[WME_AC_BK])
588138570Ssam		ic->ic_caps |= IEEE80211_C_WME;
589138570Ssam	/*
590147057Ssam	 * Check for misc other capabilities.
591138570Ssam	 */
592138570Ssam	if (ath_hal_hasbursting(ah))
593138570Ssam		ic->ic_caps |= IEEE80211_C_BURST;
594178354Ssam	sc->sc_hasbmask = ath_hal_hasbssidmask(ah);
595195618Srpaulo	sc->sc_hasbmatch = ath_hal_hasbssidmatch(ah);
596178354Ssam	sc->sc_hastsfadd = ath_hal_hastsfadjust(ah);
597220324Sadrian	sc->sc_rxslink = ath_hal_self_linked_final_rxdesc(ah);
598225444Sadrian	sc->sc_rxtsf32 = ath_hal_has_long_rxdesc_tsf(ah);
599170530Ssam	if (ath_hal_hasfastframes(ah))
600170530Ssam		ic->ic_caps |= IEEE80211_C_FF;
601187831Ssam	wmodes = ath_hal_getwirelessmodes(ah);
602184369Ssam	if (wmodes & (HAL_MODE_108G|HAL_MODE_TURBO))
603170530Ssam		ic->ic_caps |= IEEE80211_C_TURBOP;
604190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
605186904Ssam	if (ath_hal_macversion(ah) > 0x78) {
606186904Ssam		ic->ic_caps |= IEEE80211_C_TDMA; /* capable of TDMA */
607186904Ssam		ic->ic_tdma_update = ath_tdma_update;
608186904Ssam	}
609186904Ssam#endif
610218488Sadrian
611138570Ssam	/*
612218488Sadrian	 * The if_ath 11n support is completely not ready for normal use.
613218488Sadrian	 * Enabling this option will likely break everything and everything.
614218488Sadrian	 * Don't think of doing that unless you know what you're doing.
615218488Sadrian	 */
616218488Sadrian
617220053Sadrian#ifdef	ATH_ENABLE_11N
618218488Sadrian	/*
619218488Sadrian	 * Query HT capabilities
620218488Sadrian	 */
621218488Sadrian	if (ath_hal_getcapability(ah, HAL_CAP_HT, 0, NULL) == HAL_OK &&
622218488Sadrian	    (wmodes & (HAL_MODE_HT20 | HAL_MODE_HT40))) {
623218488Sadrian		int rxs, txs;
624218488Sadrian
625218488Sadrian		device_printf(sc->sc_dev, "[HT] enabling HT modes\n");
626218488Sadrian		ic->ic_htcaps = IEEE80211_HTC_HT		/* HT operation */
627218488Sadrian			    | IEEE80211_HTC_AMPDU		/* A-MPDU tx/rx */
628218488Sadrian			    | IEEE80211_HTC_AMSDU		/* A-MSDU tx/rx */
629218488Sadrian			    | IEEE80211_HTCAP_MAXAMSDU_3839	/* max A-MSDU length */
630218488Sadrian			    | IEEE80211_HTCAP_SMPS_OFF;		/* SM power save off */
631218488Sadrian			;
632218488Sadrian
633222432Sadrian		/*
634222432Sadrian		 * Enable short-GI for HT20 only if the hardware
635222432Sadrian		 * advertises support.
636222432Sadrian		 * Notably, anything earlier than the AR9287 doesn't.
637222432Sadrian		 */
638222432Sadrian		if ((ath_hal_getcapability(ah,
639222432Sadrian		    HAL_CAP_HT20_SGI, 0, NULL) == HAL_OK) &&
640222432Sadrian		    (wmodes & HAL_MODE_HT20)) {
641222432Sadrian			device_printf(sc->sc_dev,
642222432Sadrian			    "[HT] enabling short-GI in 20MHz mode\n");
643222432Sadrian			ic->ic_htcaps |= IEEE80211_HTCAP_SHORTGI20;
644222432Sadrian		}
645222432Sadrian
646218488Sadrian		if (wmodes & HAL_MODE_HT40)
647218488Sadrian			ic->ic_htcaps |= IEEE80211_HTCAP_CHWIDTH40
648218488Sadrian			    |  IEEE80211_HTCAP_SHORTGI40;
649218488Sadrian
650218488Sadrian		/*
651218488Sadrian		 * rx/tx stream is not currently used anywhere; it needs to be taken
652218488Sadrian		 * into account when negotiating which MCS rates it'll receive and
653218488Sadrian		 * what MCS rates are available for TX.
654218488Sadrian		 */
655218488Sadrian		(void) ath_hal_getcapability(ah, HAL_CAP_STREAMS, 0, &rxs);
656218488Sadrian		(void) ath_hal_getcapability(ah, HAL_CAP_STREAMS, 1, &txs);
657218488Sadrian
658218488Sadrian		ath_hal_getrxchainmask(ah, &sc->sc_rxchainmask);
659218488Sadrian		ath_hal_gettxchainmask(ah, &sc->sc_txchainmask);
660218488Sadrian
661218488Sadrian		ic->ic_txstream = txs;
662218488Sadrian		ic->ic_rxstream = rxs;
663218488Sadrian
664218488Sadrian		device_printf(sc->sc_dev, "[HT] %d RX streams; %d TX streams\n", rxs, txs);
665218488Sadrian	}
666218488Sadrian#endif
667218488Sadrian
668218488Sadrian	/*
669138570Ssam	 * Indicate we need the 802.11 header padded to a
670138570Ssam	 * 32-bit boundary for 4-address and QoS frames.
671138570Ssam	 */
672138570Ssam	ic->ic_flags |= IEEE80211_F_DATAPAD;
673138570Ssam
674138570Ssam	/*
675138570Ssam	 * Query the hal about antenna support.
676138570Ssam	 */
677138570Ssam	sc->sc_defant = ath_hal_getdefantenna(ah);
678138570Ssam
679138570Ssam	/*
680138570Ssam	 * Not all chips have the VEOL support we want to
681138570Ssam	 * use with IBSS beacons; check here for it.
682138570Ssam	 */
683138570Ssam	sc->sc_hasveol = ath_hal_hasveol(ah);
684138570Ssam
685116743Ssam	/* get mac address from hardware */
686190526Ssam	ath_hal_getmac(ah, macaddr);
687178354Ssam	if (sc->sc_hasbmask)
688178354Ssam		ath_hal_getbssidmask(ah, sc->sc_hwbssidmask);
689116743Ssam
690178354Ssam	/* NB: used to size node table key mapping array */
691178354Ssam	ic->ic_max_keyix = sc->sc_keymax;
692116743Ssam	/* call MI attach routine. */
693190526Ssam	ieee80211_ifattach(ic, macaddr);
694178354Ssam	ic->ic_setregdomain = ath_setregdomain;
695178354Ssam	ic->ic_getradiocaps = ath_getradiocaps;
696178354Ssam	sc->sc_opmode = HAL_M_STA;
697178354Ssam
698116743Ssam	/* override default methods */
699178354Ssam	ic->ic_newassoc = ath_newassoc;
700178354Ssam	ic->ic_updateslot = ath_updateslot;
701178354Ssam	ic->ic_wme.wme_update = ath_wme_update;
702178354Ssam	ic->ic_vap_create = ath_vap_create;
703178354Ssam	ic->ic_vap_delete = ath_vap_delete;
704178354Ssam	ic->ic_raw_xmit = ath_raw_xmit;
705178354Ssam	ic->ic_update_mcast = ath_update_mcast;
706178354Ssam	ic->ic_update_promisc = ath_update_promisc;
707116743Ssam	ic->ic_node_alloc = ath_node_alloc;
708127782Ssam	sc->sc_node_free = ic->ic_node_free;
709116743Ssam	ic->ic_node_free = ath_node_free;
710170530Ssam	ic->ic_node_getsignal = ath_node_getsignal;
711170530Ssam	ic->ic_scan_start = ath_scan_start;
712170530Ssam	ic->ic_scan_end = ath_scan_end;
713170530Ssam	ic->ic_set_channel = ath_set_channel;
714116743Ssam
715192468Ssam	ieee80211_radiotap_attach(ic,
716192468Ssam	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
717192468Ssam		ATH_TX_RADIOTAP_PRESENT,
718192468Ssam	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
719192468Ssam		ATH_RX_RADIOTAP_PRESENT);
720192468Ssam
721148326Ssam	/*
722148326Ssam	 * Setup dynamic sysctl's now that country code and
723148326Ssam	 * regdomain are available from the hal.
724148326Ssam	 */
725148326Ssam	ath_sysctlattach(sc);
726211303Sadrian	ath_sysctl_stats_attach(sc);
727223459Sadrian	ath_sysctl_hal_attach(sc);
728119783Ssam
729138570Ssam	if (bootverbose)
730138570Ssam		ieee80211_announce(ic);
731138570Ssam	ath_announce(sc);
732116743Ssam	return 0;
733127777Ssambad2:
734138570Ssam	ath_tx_cleanup(sc);
735127777Ssam	ath_desc_free(sc);
736116743Ssambad:
737116743Ssam	if (ah)
738116743Ssam		ath_hal_detach(ah);
739147256Sbrooks	if (ifp != NULL)
740147256Sbrooks		if_free(ifp);
741116743Ssam	sc->sc_invalid = 1;
742116743Ssam	return error;
743116743Ssam}
744116743Ssam
745116743Ssamint
746116743Ssamath_detach(struct ath_softc *sc)
747116743Ssam{
748147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
749116743Ssam
750138570Ssam	DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
751138570Ssam		__func__, ifp->if_flags);
752116743Ssam
753204100Sdeischen	/*
754138570Ssam	 * NB: the order of these is important:
755179400Ssam	 * o stop the chip so no more interrupts will fire
756138570Ssam	 * o call the 802.11 layer before detaching the hal to
757138570Ssam	 *   insure callbacks into the driver to delete global
758138570Ssam	 *   key cache entries can be handled
759179400Ssam	 * o free the taskqueue which drains any pending tasks
760138570Ssam	 * o reclaim the tx queue data structures after calling
761138570Ssam	 *   the 802.11 layer as we'll get called back to reclaim
762138570Ssam	 *   node state and potentially want to use them
763138570Ssam	 * o to cleanup the tx queues the hal is called, so detach
764138570Ssam	 *   it last
765138570Ssam	 * Other than that, it's straightforward...
766138570Ssam	 */
767179400Ssam	ath_stop(ifp);
768178354Ssam	ieee80211_ifdetach(ifp->if_l2com);
769179400Ssam	taskqueue_free(sc->sc_tq);
770155486Ssam#ifdef ATH_TX99_DIAG
771155486Ssam	if (sc->sc_tx99 != NULL)
772155486Ssam		sc->sc_tx99->detach(sc->sc_tx99);
773155486Ssam#endif
774138570Ssam	ath_rate_detach(sc->sc_rc);
775222585Sadrian
776222585Sadrian	ath_dfs_detach(sc);
777116743Ssam	ath_desc_free(sc);
778138570Ssam	ath_tx_cleanup(sc);
779179400Ssam	ath_hal_detach(sc->sc_ah);	/* NB: sets chip in full sleep */
780150212Sru	if_free(ifp);
781121100Ssam
782116743Ssam	return 0;
783116743Ssam}
784116743Ssam
785178354Ssam/*
786178354Ssam * MAC address handling for multiple BSS on the same radio.
787178354Ssam * The first vap uses the MAC address from the EEPROM.  For
788178354Ssam * subsequent vap's we set the U/L bit (bit 1) in the MAC
789178354Ssam * address and use the next six bits as an index.
790178354Ssam */
791178354Ssamstatic void
792178354Ssamassign_address(struct ath_softc *sc, uint8_t mac[IEEE80211_ADDR_LEN], int clone)
793178354Ssam{
794178354Ssam	int i;
795178354Ssam
796178354Ssam	if (clone && sc->sc_hasbmask) {
797178354Ssam		/* NB: we only do this if h/w supports multiple bssid */
798178354Ssam		for (i = 0; i < 8; i++)
799178354Ssam			if ((sc->sc_bssidmask & (1<<i)) == 0)
800178354Ssam				break;
801178354Ssam		if (i != 0)
802178354Ssam			mac[0] |= (i << 2)|0x2;
803178354Ssam	} else
804178354Ssam		i = 0;
805178354Ssam	sc->sc_bssidmask |= 1<<i;
806178354Ssam	sc->sc_hwbssidmask[0] &= ~mac[0];
807178354Ssam	if (i == 0)
808178354Ssam		sc->sc_nbssid0++;
809178354Ssam}
810178354Ssam
811178354Ssamstatic void
812178354Ssamreclaim_address(struct ath_softc *sc, const uint8_t mac[IEEE80211_ADDR_LEN])
813178354Ssam{
814178354Ssam	int i = mac[0] >> 2;
815178354Ssam	uint8_t mask;
816178354Ssam
817178354Ssam	if (i != 0 || --sc->sc_nbssid0 == 0) {
818178354Ssam		sc->sc_bssidmask &= ~(1<<i);
819178354Ssam		/* recalculate bssid mask from remaining addresses */
820178354Ssam		mask = 0xff;
821178354Ssam		for (i = 1; i < 8; i++)
822178354Ssam			if (sc->sc_bssidmask & (1<<i))
823178354Ssam				mask &= ~((i<<2)|0x2);
824178354Ssam		sc->sc_hwbssidmask[0] |= mask;
825178354Ssam	}
826178354Ssam}
827178354Ssam
828178354Ssam/*
829178354Ssam * Assign a beacon xmit slot.  We try to space out
830178354Ssam * assignments so when beacons are staggered the
831178354Ssam * traffic coming out of the cab q has maximal time
832178354Ssam * to go out before the next beacon is scheduled.
833178354Ssam */
834178354Ssamstatic int
835178354Ssamassign_bslot(struct ath_softc *sc)
836178354Ssam{
837178354Ssam	u_int slot, free;
838178354Ssam
839178354Ssam	free = 0;
840178354Ssam	for (slot = 0; slot < ATH_BCBUF; slot++)
841178354Ssam		if (sc->sc_bslot[slot] == NULL) {
842178354Ssam			if (sc->sc_bslot[(slot+1)%ATH_BCBUF] == NULL &&
843178354Ssam			    sc->sc_bslot[(slot-1)%ATH_BCBUF] == NULL)
844178354Ssam				return slot;
845178354Ssam			free = slot;
846178354Ssam			/* NB: keep looking for a double slot */
847178354Ssam		}
848178354Ssam	return free;
849178354Ssam}
850178354Ssam
851178354Ssamstatic struct ieee80211vap *
852234753Sdimath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
853234753Sdim    enum ieee80211_opmode opmode, int flags,
854234753Sdim    const uint8_t bssid[IEEE80211_ADDR_LEN],
855234753Sdim    const uint8_t mac0[IEEE80211_ADDR_LEN])
856178354Ssam{
857178354Ssam	struct ath_softc *sc = ic->ic_ifp->if_softc;
858178354Ssam	struct ath_vap *avp;
859178354Ssam	struct ieee80211vap *vap;
860178354Ssam	uint8_t mac[IEEE80211_ADDR_LEN];
861234753Sdim	int needbeacon, error;
862234753Sdim	enum ieee80211_opmode ic_opmode;
863178354Ssam
864178354Ssam	avp = (struct ath_vap *) malloc(sizeof(struct ath_vap),
865178354Ssam	    M_80211_VAP, M_WAITOK | M_ZERO);
866178354Ssam	needbeacon = 0;
867178354Ssam	IEEE80211_ADDR_COPY(mac, mac0);
868178354Ssam
869178354Ssam	ATH_LOCK(sc);
870191865Ssam	ic_opmode = opmode;		/* default to opmode of new vap */
871178354Ssam	switch (opmode) {
872178354Ssam	case IEEE80211_M_STA:
873191865Ssam		if (sc->sc_nstavaps != 0) {	/* XXX only 1 for now */
874178354Ssam			device_printf(sc->sc_dev, "only 1 sta vap supported\n");
875178354Ssam			goto bad;
876178354Ssam		}
877178354Ssam		if (sc->sc_nvaps) {
878178354Ssam			/*
879191865Ssam			 * With multiple vaps we must fall back
880191865Ssam			 * to s/w beacon miss handling.
881178354Ssam			 */
882178354Ssam			flags |= IEEE80211_CLONE_NOBEACONS;
883178354Ssam		}
884191865Ssam		if (flags & IEEE80211_CLONE_NOBEACONS) {
885191865Ssam			/*
886191865Ssam			 * Station mode w/o beacons are implemented w/ AP mode.
887191865Ssam			 */
888178354Ssam			ic_opmode = IEEE80211_M_HOSTAP;
889191865Ssam		}
890178354Ssam		break;
891178354Ssam	case IEEE80211_M_IBSS:
892178354Ssam		if (sc->sc_nvaps != 0) {	/* XXX only 1 for now */
893178354Ssam			device_printf(sc->sc_dev,
894178354Ssam			    "only 1 ibss vap supported\n");
895178354Ssam			goto bad;
896178354Ssam		}
897178354Ssam		needbeacon = 1;
898178354Ssam		break;
899178354Ssam	case IEEE80211_M_AHDEMO:
900190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
901186904Ssam		if (flags & IEEE80211_CLONE_TDMA) {
902191865Ssam			if (sc->sc_nvaps != 0) {
903191865Ssam				device_printf(sc->sc_dev,
904191865Ssam				    "only 1 tdma vap supported\n");
905191865Ssam				goto bad;
906191865Ssam			}
907186904Ssam			needbeacon = 1;
908186904Ssam			flags |= IEEE80211_CLONE_NOBEACONS;
909186904Ssam		}
910178354Ssam		/* fall thru... */
911186904Ssam#endif
912178354Ssam	case IEEE80211_M_MONITOR:
913178354Ssam		if (sc->sc_nvaps != 0 && ic->ic_opmode != opmode) {
914191865Ssam			/*
915191865Ssam			 * Adopt existing mode.  Adding a monitor or ahdemo
916191865Ssam			 * vap to an existing configuration is of dubious
917191865Ssam			 * value but should be ok.
918191865Ssam			 */
919178354Ssam			/* XXX not right for monitor mode */
920178354Ssam			ic_opmode = ic->ic_opmode;
921191865Ssam		}
922178354Ssam		break;
923178354Ssam	case IEEE80211_M_HOSTAP:
924195618Srpaulo	case IEEE80211_M_MBSS:
925178354Ssam		needbeacon = 1;
926191865Ssam		break;
927178354Ssam	case IEEE80211_M_WDS:
928191865Ssam		if (sc->sc_nvaps != 0 && ic->ic_opmode == IEEE80211_M_STA) {
929178354Ssam			device_printf(sc->sc_dev,
930178354Ssam			    "wds not supported in sta mode\n");
931178354Ssam			goto bad;
932178354Ssam		}
933191865Ssam		/*
934191865Ssam		 * Silently remove any request for a unique
935191865Ssam		 * bssid; WDS vap's always share the local
936191865Ssam		 * mac address.
937191865Ssam		 */
938191865Ssam		flags &= ~IEEE80211_CLONE_BSSID;
939191865Ssam		if (sc->sc_nvaps == 0)
940191865Ssam			ic_opmode = IEEE80211_M_HOSTAP;
941191865Ssam		else
942191865Ssam			ic_opmode = ic->ic_opmode;
943195620Srpaulo		break;
944178354Ssam	default:
945178354Ssam		device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
946178354Ssam		goto bad;
947178354Ssam	}
948178354Ssam	/*
949178354Ssam	 * Check that a beacon buffer is available; the code below assumes it.
950178354Ssam	 */
951178354Ssam	if (needbeacon & STAILQ_EMPTY(&sc->sc_bbuf)) {
952178354Ssam		device_printf(sc->sc_dev, "no beacon buffer available\n");
953178354Ssam		goto bad;
954178354Ssam	}
955178354Ssam
956178354Ssam	/* STA, AHDEMO? */
957195618Srpaulo	if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_MBSS) {
958178354Ssam		assign_address(sc, mac, flags & IEEE80211_CLONE_BSSID);
959178354Ssam		ath_hal_setbssidmask(sc->sc_ah, sc->sc_hwbssidmask);
960178354Ssam	}
961178354Ssam
962178354Ssam	vap = &avp->av_vap;
963178354Ssam	/* XXX can't hold mutex across if_alloc */
964178354Ssam	ATH_UNLOCK(sc);
965178354Ssam	error = ieee80211_vap_setup(ic, vap, name, unit, opmode, flags,
966178354Ssam	    bssid, mac);
967178354Ssam	ATH_LOCK(sc);
968178354Ssam	if (error != 0) {
969178354Ssam		device_printf(sc->sc_dev, "%s: error %d creating vap\n",
970178354Ssam		    __func__, error);
971178354Ssam		goto bad2;
972178354Ssam	}
973178354Ssam
974178354Ssam	/* h/w crypto support */
975178354Ssam	vap->iv_key_alloc = ath_key_alloc;
976178354Ssam	vap->iv_key_delete = ath_key_delete;
977178354Ssam	vap->iv_key_set = ath_key_set;
978178354Ssam	vap->iv_key_update_begin = ath_key_update_begin;
979178354Ssam	vap->iv_key_update_end = ath_key_update_end;
980178354Ssam
981178354Ssam	/* override various methods */
982178354Ssam	avp->av_recv_mgmt = vap->iv_recv_mgmt;
983178354Ssam	vap->iv_recv_mgmt = ath_recv_mgmt;
984178354Ssam	vap->iv_reset = ath_reset_vap;
985178354Ssam	vap->iv_update_beacon = ath_beacon_update;
986178354Ssam	avp->av_newstate = vap->iv_newstate;
987178354Ssam	vap->iv_newstate = ath_newstate;
988178354Ssam	avp->av_bmiss = vap->iv_bmiss;
989178354Ssam	vap->iv_bmiss = ath_bmiss_vap;
990178354Ssam
991222497Sadrian	/* Set default parameters */
992222497Sadrian
993222497Sadrian	/*
994222497Sadrian	 * Anything earlier than some AR9300 series MACs don't
995222497Sadrian	 * support a smaller MPDU density.
996222497Sadrian	 */
997222497Sadrian	vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_8;
998222497Sadrian	/*
999222497Sadrian	 * All NICs can handle the maximum size, however
1000222497Sadrian	 * AR5416 based MACs can only TX aggregates w/ RTS
1001222497Sadrian	 * protection when the total aggregate size is <= 8k.
1002222497Sadrian	 * However, for now that's enforced by the TX path.
1003222497Sadrian	 */
1004222497Sadrian	vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K;
1005222497Sadrian
1006178354Ssam	avp->av_bslot = -1;
1007178354Ssam	if (needbeacon) {
1008178354Ssam		/*
1009178354Ssam		 * Allocate beacon state and setup the q for buffered
1010178354Ssam		 * multicast frames.  We know a beacon buffer is
1011178354Ssam		 * available because we checked above.
1012178354Ssam		 */
1013178354Ssam		avp->av_bcbuf = STAILQ_FIRST(&sc->sc_bbuf);
1014178354Ssam		STAILQ_REMOVE_HEAD(&sc->sc_bbuf, bf_list);
1015178354Ssam		if (opmode != IEEE80211_M_IBSS || !sc->sc_hasveol) {
1016178354Ssam			/*
1017178354Ssam			 * Assign the vap to a beacon xmit slot.  As above
1018178354Ssam			 * this cannot fail to find a free one.
1019178354Ssam			 */
1020178354Ssam			avp->av_bslot = assign_bslot(sc);
1021178354Ssam			KASSERT(sc->sc_bslot[avp->av_bslot] == NULL,
1022178354Ssam			    ("beacon slot %u not empty", avp->av_bslot));
1023178354Ssam			sc->sc_bslot[avp->av_bslot] = vap;
1024178354Ssam			sc->sc_nbcnvaps++;
1025178354Ssam		}
1026178354Ssam		if (sc->sc_hastsfadd && sc->sc_nbcnvaps > 0) {
1027178354Ssam			/*
1028178354Ssam			 * Multple vaps are to transmit beacons and we
1029178354Ssam			 * have h/w support for TSF adjusting; enable
1030178354Ssam			 * use of staggered beacons.
1031178354Ssam			 */
1032178354Ssam			sc->sc_stagbeacons = 1;
1033178354Ssam		}
1034178354Ssam		ath_txq_init(sc, &avp->av_mcastq, ATH_TXQ_SWQ);
1035178354Ssam	}
1036178354Ssam
1037178354Ssam	ic->ic_opmode = ic_opmode;
1038178354Ssam	if (opmode != IEEE80211_M_WDS) {
1039178354Ssam		sc->sc_nvaps++;
1040178354Ssam		if (opmode == IEEE80211_M_STA)
1041178354Ssam			sc->sc_nstavaps++;
1042195807Ssam		if (opmode == IEEE80211_M_MBSS)
1043195807Ssam			sc->sc_nmeshvaps++;
1044178354Ssam	}
1045178354Ssam	switch (ic_opmode) {
1046178354Ssam	case IEEE80211_M_IBSS:
1047178354Ssam		sc->sc_opmode = HAL_M_IBSS;
1048178354Ssam		break;
1049178354Ssam	case IEEE80211_M_STA:
1050178354Ssam		sc->sc_opmode = HAL_M_STA;
1051178354Ssam		break;
1052178354Ssam	case IEEE80211_M_AHDEMO:
1053190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
1054186904Ssam		if (vap->iv_caps & IEEE80211_C_TDMA) {
1055186904Ssam			sc->sc_tdma = 1;
1056186904Ssam			/* NB: disable tsf adjust */
1057186904Ssam			sc->sc_stagbeacons = 0;
1058186904Ssam		}
1059186904Ssam		/*
1060186904Ssam		 * NB: adhoc demo mode is a pseudo mode; to the hal it's
1061186904Ssam		 * just ap mode.
1062186904Ssam		 */
1063186904Ssam		/* fall thru... */
1064186904Ssam#endif
1065178354Ssam	case IEEE80211_M_HOSTAP:
1066195618Srpaulo	case IEEE80211_M_MBSS:
1067178354Ssam		sc->sc_opmode = HAL_M_HOSTAP;
1068178354Ssam		break;
1069178354Ssam	case IEEE80211_M_MONITOR:
1070178354Ssam		sc->sc_opmode = HAL_M_MONITOR;
1071178354Ssam		break;
1072178354Ssam	default:
1073178354Ssam		/* XXX should not happen */
1074178354Ssam		break;
1075178354Ssam	}
1076178354Ssam	if (sc->sc_hastsfadd) {
1077178354Ssam		/*
1078178354Ssam		 * Configure whether or not TSF adjust should be done.
1079178354Ssam		 */
1080178354Ssam		ath_hal_settsfadjust(sc->sc_ah, sc->sc_stagbeacons);
1081178354Ssam	}
1082186904Ssam	if (flags & IEEE80211_CLONE_NOBEACONS) {
1083186904Ssam		/*
1084186904Ssam		 * Enable s/w beacon miss handling.
1085186904Ssam		 */
1086186904Ssam		sc->sc_swbmiss = 1;
1087186904Ssam	}
1088178354Ssam	ATH_UNLOCK(sc);
1089178354Ssam
1090178354Ssam	/* complete setup */
1091178354Ssam	ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status);
1092178354Ssam	return vap;
1093178354Ssambad2:
1094178354Ssam	reclaim_address(sc, mac);
1095178354Ssam	ath_hal_setbssidmask(sc->sc_ah, sc->sc_hwbssidmask);
1096178354Ssambad:
1097178354Ssam	free(avp, M_80211_VAP);
1098178354Ssam	ATH_UNLOCK(sc);
1099178354Ssam	return NULL;
1100178354Ssam}
1101178354Ssam
1102178354Ssamstatic void
1103178354Ssamath_vap_delete(struct ieee80211vap *vap)
1104178354Ssam{
1105178354Ssam	struct ieee80211com *ic = vap->iv_ic;
1106178354Ssam	struct ifnet *ifp = ic->ic_ifp;
1107178354Ssam	struct ath_softc *sc = ifp->if_softc;
1108178354Ssam	struct ath_hal *ah = sc->sc_ah;
1109178354Ssam	struct ath_vap *avp = ATH_VAP(vap);
1110178354Ssam
1111178354Ssam	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1112178354Ssam		/*
1113178354Ssam		 * Quiesce the hardware while we remove the vap.  In
1114178354Ssam		 * particular we need to reclaim all references to
1115178354Ssam		 * the vap state by any frames pending on the tx queues.
1116178354Ssam		 */
1117178354Ssam		ath_hal_intrset(ah, 0);		/* disable interrupts */
1118178354Ssam		ath_draintxq(sc);		/* stop xmit side */
1119178354Ssam		ath_stoprecv(sc);		/* stop recv side */
1120178354Ssam	}
1121178354Ssam
1122178354Ssam	ieee80211_vap_detach(vap);
1123178354Ssam	ATH_LOCK(sc);
1124178354Ssam	/*
1125178354Ssam	 * Reclaim beacon state.  Note this must be done before
1126178354Ssam	 * the vap instance is reclaimed as we may have a reference
1127178354Ssam	 * to it in the buffer for the beacon frame.
1128178354Ssam	 */
1129178354Ssam	if (avp->av_bcbuf != NULL) {
1130178354Ssam		if (avp->av_bslot != -1) {
1131178354Ssam			sc->sc_bslot[avp->av_bslot] = NULL;
1132178354Ssam			sc->sc_nbcnvaps--;
1133178354Ssam		}
1134178354Ssam		ath_beacon_return(sc, avp->av_bcbuf);
1135178354Ssam		avp->av_bcbuf = NULL;
1136178354Ssam		if (sc->sc_nbcnvaps == 0) {
1137178354Ssam			sc->sc_stagbeacons = 0;
1138178354Ssam			if (sc->sc_hastsfadd)
1139178354Ssam				ath_hal_settsfadjust(sc->sc_ah, 0);
1140178354Ssam		}
1141178354Ssam		/*
1142178354Ssam		 * Reclaim any pending mcast frames for the vap.
1143178354Ssam		 */
1144178354Ssam		ath_tx_draintxq(sc, &avp->av_mcastq);
1145178354Ssam		ATH_TXQ_LOCK_DESTROY(&avp->av_mcastq);
1146178354Ssam	}
1147178354Ssam	/*
1148178354Ssam	 * Update bookkeeping.
1149178354Ssam	 */
1150178354Ssam	if (vap->iv_opmode == IEEE80211_M_STA) {
1151178354Ssam		sc->sc_nstavaps--;
1152178354Ssam		if (sc->sc_nstavaps == 0 && sc->sc_swbmiss)
1153178354Ssam			sc->sc_swbmiss = 0;
1154195618Srpaulo	} else if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
1155195618Srpaulo	    vap->iv_opmode == IEEE80211_M_MBSS) {
1156178354Ssam		reclaim_address(sc, vap->iv_myaddr);
1157178354Ssam		ath_hal_setbssidmask(ah, sc->sc_hwbssidmask);
1158195807Ssam		if (vap->iv_opmode == IEEE80211_M_MBSS)
1159195807Ssam			sc->sc_nmeshvaps--;
1160178354Ssam	}
1161178354Ssam	if (vap->iv_opmode != IEEE80211_M_WDS)
1162178354Ssam		sc->sc_nvaps--;
1163190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
1164186904Ssam	/* TDMA operation ceases when the last vap is destroyed */
1165186904Ssam	if (sc->sc_tdma && sc->sc_nvaps == 0) {
1166186904Ssam		sc->sc_tdma = 0;
1167186904Ssam		sc->sc_swbmiss = 0;
1168186904Ssam	}
1169186904Ssam#endif
1170178354Ssam	ATH_UNLOCK(sc);
1171178354Ssam	free(avp, M_80211_VAP);
1172178354Ssam
1173178354Ssam	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1174178354Ssam		/*
1175178354Ssam		 * Restart rx+tx machines if still running (RUNNING will
1176178354Ssam		 * be reset if we just destroyed the last vap).
1177178354Ssam		 */
1178178354Ssam		if (ath_startrecv(sc) != 0)
1179178354Ssam			if_printf(ifp, "%s: unable to restart recv logic\n",
1180178354Ssam			    __func__);
1181193349Ssam		if (sc->sc_beacons) {		/* restart beacons */
1182193349Ssam#ifdef IEEE80211_SUPPORT_TDMA
1183193349Ssam			if (sc->sc_tdma)
1184193349Ssam				ath_tdma_config(sc, NULL);
1185193349Ssam			else
1186193349Ssam#endif
1187193349Ssam				ath_beacon_config(sc, NULL);
1188193349Ssam		}
1189178354Ssam		ath_hal_intrset(ah, sc->sc_imask);
1190178354Ssam	}
1191178354Ssam}
1192178354Ssam
1193116743Ssamvoid
1194116743Ssamath_suspend(struct ath_softc *sc)
1195116743Ssam{
1196147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
1197179401Ssam	struct ieee80211com *ic = ifp->if_l2com;
1198116743Ssam
1199138570Ssam	DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
1200138570Ssam		__func__, ifp->if_flags);
1201116743Ssam
1202179401Ssam	sc->sc_resume_up = (ifp->if_flags & IFF_UP) != 0;
1203179401Ssam	if (ic->ic_opmode == IEEE80211_M_STA)
1204179401Ssam		ath_stop(ifp);
1205179401Ssam	else
1206179401Ssam		ieee80211_suspend_all(ic);
1207179401Ssam	/*
1208179401Ssam	 * NB: don't worry about putting the chip in low power
1209179401Ssam	 * mode; pci will power off our socket on suspend and
1210201453Simp	 * CardBus detaches the device.
1211179401Ssam	 */
1212116743Ssam}
1213116743Ssam
1214179401Ssam/*
1215179401Ssam * Reset the key cache since some parts do not reset the
1216179401Ssam * contents on resume.  First we clear all entries, then
1217179401Ssam * re-load keys that the 802.11 layer assumes are setup
1218179401Ssam * in h/w.
1219179401Ssam */
1220179401Ssamstatic void
1221179401Ssamath_reset_keycache(struct ath_softc *sc)
1222179401Ssam{
1223179401Ssam	struct ifnet *ifp = sc->sc_ifp;
1224179401Ssam	struct ieee80211com *ic = ifp->if_l2com;
1225179401Ssam	struct ath_hal *ah = sc->sc_ah;
1226179401Ssam	int i;
1227179401Ssam
1228179401Ssam	for (i = 0; i < sc->sc_keymax; i++)
1229179401Ssam		ath_hal_keyreset(ah, i);
1230179401Ssam	ieee80211_crypto_reload_keys(ic);
1231179401Ssam}
1232179401Ssam
1233116743Ssamvoid
1234116743Ssamath_resume(struct ath_softc *sc)
1235116743Ssam{
1236147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
1237179401Ssam	struct ieee80211com *ic = ifp->if_l2com;
1238179401Ssam	struct ath_hal *ah = sc->sc_ah;
1239179401Ssam	HAL_STATUS status;
1240116743Ssam
1241138570Ssam	DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
1242138570Ssam		__func__, ifp->if_flags);
1243116743Ssam
1244179401Ssam	/*
1245179401Ssam	 * Must reset the chip before we reload the
1246179401Ssam	 * keycache as we were powered down on suspend.
1247179401Ssam	 */
1248188445Ssam	ath_hal_reset(ah, sc->sc_opmode,
1249188445Ssam	    sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan,
1250188445Ssam	    AH_FALSE, &status);
1251179401Ssam	ath_reset_keycache(sc);
1252222668Sadrian
1253222668Sadrian	/* Let DFS at it in case it's a DFS channel */
1254222668Sadrian	ath_dfs_radar_enable(sc, ic->ic_curchan);
1255222668Sadrian
1256179401Ssam	if (sc->sc_resume_up) {
1257179401Ssam		if (ic->ic_opmode == IEEE80211_M_STA) {
1258179401Ssam			ath_init(sc);
1259196717Ssam			/*
1260196717Ssam			 * Program the beacon registers using the last rx'd
1261196717Ssam			 * beacon frame and enable sync on the next beacon
1262196717Ssam			 * we see.  This should handle the case where we
1263196717Ssam			 * wakeup and find the same AP and also the case where
1264196717Ssam			 * we wakeup and need to roam.  For the latter we
1265196717Ssam			 * should get bmiss events that trigger a roam.
1266196717Ssam			 */
1267196717Ssam			ath_beacon_config(sc, NULL);
1268196717Ssam			sc->sc_syncbeacon = 1;
1269179401Ssam		} else
1270179401Ssam			ieee80211_resume_all(ic);
1271118342Ssam	}
1272146885Ssam	if (sc->sc_softled) {
1273188974Ssam		ath_hal_gpioCfgOutput(ah, sc->sc_ledpin,
1274188974Ssam		    HAL_GPIO_MUX_MAC_NETWORK_LED);
1275179401Ssam		ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon);
1276146885Ssam	}
1277223568Sadrian
1278223568Sadrian	/* XXX beacons ? */
1279116743Ssam}
1280116743Ssam
1281116743Ssamvoid
1282116743Ssamath_shutdown(struct ath_softc *sc)
1283116743Ssam{
1284147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
1285116743Ssam
1286138570Ssam	DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
1287138570Ssam		__func__, ifp->if_flags);
1288116743Ssam
1289116743Ssam	ath_stop(ifp);
1290179401Ssam	/* NB: no point powering down chip as we're about to reboot */
1291116743Ssam}
1292116743Ssam
1293138570Ssam/*
1294138570Ssam * Interrupt handler.  Most of the actual processing is deferred.
1295138570Ssam */
1296116743Ssamvoid
1297116743Ssamath_intr(void *arg)
1298116743Ssam{
1299116743Ssam	struct ath_softc *sc = arg;
1300147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
1301116743Ssam	struct ath_hal *ah = sc->sc_ah;
1302220966Sadrian	HAL_INT status = 0;
1303116743Ssam
1304116743Ssam	if (sc->sc_invalid) {
1305116743Ssam		/*
1306118884Ssam		 * The hardware is not ready/present, don't touch anything.
1307118884Ssam		 * Note this can happen early on if the IRQ is shared.
1308116743Ssam		 */
1309138570Ssam		DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid; ignored\n", __func__);
1310116743Ssam		return;
1311116743Ssam	}
1312127778Ssam	if (!ath_hal_intrpend(ah))		/* shared irq, not for us */
1313127778Ssam		return;
1314170530Ssam	if ((ifp->if_flags & IFF_UP) == 0 ||
1315170530Ssam	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
1316170530Ssam		HAL_INT status;
1317170530Ssam
1318138570Ssam		DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
1319138570Ssam			__func__, ifp->if_flags);
1320116743Ssam		ath_hal_getisr(ah, &status);	/* clear ISR */
1321116743Ssam		ath_hal_intrset(ah, 0);		/* disable further intr's */
1322116743Ssam		return;
1323116743Ssam	}
1324138570Ssam	/*
1325138570Ssam	 * Figure out the reason(s) for the interrupt.  Note
1326138570Ssam	 * that the hal returns a pseudo-ISR that may include
1327138570Ssam	 * bits we haven't explicitly enabled so we mask the
1328138570Ssam	 * value to insure we only process bits we requested.
1329138570Ssam	 */
1330116743Ssam	ath_hal_getisr(ah, &status);		/* NB: clears ISR too */
1331138570Ssam	DPRINTF(sc, ATH_DEBUG_INTR, "%s: status 0x%x\n", __func__, status);
1332120100Ssam	status &= sc->sc_imask;			/* discard unasked for bits */
1333220966Sadrian
1334220966Sadrian	/* Short-circuit un-handled interrupts */
1335220966Sadrian	if (status == 0x0)
1336220966Sadrian		return;
1337220966Sadrian
1338116743Ssam	if (status & HAL_INT_FATAL) {
1339116743Ssam		sc->sc_stats.ast_hardware++;
1340116743Ssam		ath_hal_intrset(ah, 0);		/* disable intr's until reset */
1341155732Ssam		ath_fatal_proc(sc, 0);
1342116743Ssam	} else {
1343138570Ssam		if (status & HAL_INT_SWBA) {
1344138570Ssam			/*
1345138570Ssam			 * Software beacon alert--time to send a beacon.
1346138570Ssam			 * Handle beacon transmission directly; deferring
1347138570Ssam			 * this is too slow to meet timing constraints
1348138570Ssam			 * under load.
1349138570Ssam			 */
1350190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
1351186904Ssam			if (sc->sc_tdma) {
1352186904Ssam				if (sc->sc_tdmaswba == 0) {
1353186904Ssam					struct ieee80211com *ic = ifp->if_l2com;
1354186904Ssam					struct ieee80211vap *vap =
1355186904Ssam					    TAILQ_FIRST(&ic->ic_vaps);
1356186904Ssam					ath_tdma_beacon_send(sc, vap);
1357186904Ssam					sc->sc_tdmaswba =
1358186904Ssam					    vap->iv_tdma->tdma_bintval;
1359186904Ssam				} else
1360186904Ssam					sc->sc_tdmaswba--;
1361186904Ssam			} else
1362186904Ssam#endif
1363190579Ssam			{
1364186904Ssam				ath_beacon_proc(sc, 0);
1365190579Ssam#ifdef IEEE80211_SUPPORT_SUPERG
1366190579Ssam				/*
1367190579Ssam				 * Schedule the rx taskq in case there's no
1368190579Ssam				 * traffic so any frames held on the staging
1369190579Ssam				 * queue are aged and potentially flushed.
1370190579Ssam				 */
1371190579Ssam				taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
1372190579Ssam#endif
1373190579Ssam			}
1374138570Ssam		}
1375116743Ssam		if (status & HAL_INT_RXEOL) {
1376224588Sadrian			int imask = sc->sc_imask;
1377116743Ssam			/*
1378116743Ssam			 * NB: the hardware should re-read the link when
1379116743Ssam			 *     RXE bit is written, but it doesn't work at
1380116743Ssam			 *     least on older hardware revs.
1381116743Ssam			 */
1382116743Ssam			sc->sc_stats.ast_rxeol++;
1383224550Sadrian			/*
1384224550Sadrian			 * Disable RXEOL/RXORN - prevent an interrupt
1385224550Sadrian			 * storm until the PCU logic can be reset.
1386224588Sadrian			 * In case the interface is reset some other
1387224588Sadrian			 * way before "sc_kickpcu" is called, don't
1388224588Sadrian			 * modify sc_imask - that way if it is reset
1389224588Sadrian			 * by a call to ath_reset() somehow, the
1390224588Sadrian			 * interrupt mask will be correctly reprogrammed.
1391224550Sadrian			 */
1392224588Sadrian			imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN);
1393224588Sadrian			ath_hal_intrset(ah, imask);
1394224588Sadrian			/*
1395224588Sadrian			 * Enqueue an RX proc, to handled whatever
1396224588Sadrian			 * is in the RX queue.
1397224588Sadrian			 * This will then kick the PCU.
1398224588Sadrian			 */
1399224588Sadrian			taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
1400116743Ssam			sc->sc_rxlink = NULL;
1401224588Sadrian			sc->sc_kickpcu = 1;
1402116743Ssam		}
1403116743Ssam		if (status & HAL_INT_TXURN) {
1404116743Ssam			sc->sc_stats.ast_txurn++;
1405116743Ssam			/* bump tx trigger level */
1406116743Ssam			ath_hal_updatetxtriglevel(ah, AH_TRUE);
1407116743Ssam		}
1408116743Ssam		if (status & HAL_INT_RX)
1409155491Ssam			taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
1410116743Ssam		if (status & HAL_INT_TX)
1411155491Ssam			taskqueue_enqueue(sc->sc_tq, &sc->sc_txtask);
1412116743Ssam		if (status & HAL_INT_BMISS) {
1413116743Ssam			sc->sc_stats.ast_bmiss++;
1414155491Ssam			taskqueue_enqueue(sc->sc_tq, &sc->sc_bmisstask);
1415116743Ssam		}
1416220772Sadrian		if (status & HAL_INT_GTT)
1417220772Sadrian			sc->sc_stats.ast_tx_timeout++;
1418220782Sadrian		if (status & HAL_INT_CST)
1419220782Sadrian			sc->sc_stats.ast_tx_cst++;
1420138570Ssam		if (status & HAL_INT_MIB) {
1421138570Ssam			sc->sc_stats.ast_mib++;
1422138570Ssam			/*
1423138570Ssam			 * Disable interrupts until we service the MIB
1424138570Ssam			 * interrupt; otherwise it will continue to fire.
1425138570Ssam			 */
1426138570Ssam			ath_hal_intrset(ah, 0);
1427138570Ssam			/*
1428138570Ssam			 * Let the hal handle the event.  We assume it will
1429138570Ssam			 * clear whatever condition caused the interrupt.
1430138570Ssam			 */
1431155485Ssam			ath_hal_mibevent(ah, &sc->sc_halstats);
1432138570Ssam			ath_hal_intrset(ah, sc->sc_imask);
1433138570Ssam		}
1434185242Ssam		if (status & HAL_INT_RXORN) {
1435185242Ssam			/* NB: hal marks HAL_INT_FATAL when RXORN is fatal */
1436185242Ssam			sc->sc_stats.ast_rxorn++;
1437185242Ssam		}
1438116743Ssam	}
1439116743Ssam}
1440116743Ssam
1441116743Ssamstatic void
1442116743Ssamath_fatal_proc(void *arg, int pending)
1443116743Ssam{
1444116743Ssam	struct ath_softc *sc = arg;
1445147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
1446155732Ssam	u_int32_t *state;
1447155732Ssam	u_int32_t len;
1448170530Ssam	void *sp;
1449116743Ssam
1450138570Ssam	if_printf(ifp, "hardware error; resetting\n");
1451155732Ssam	/*
1452155732Ssam	 * Fatal errors are unrecoverable.  Typically these
1453155732Ssam	 * are caused by DMA errors.  Collect h/w state from
1454155732Ssam	 * the hal so we can diagnose what's going on.
1455155732Ssam	 */
1456170530Ssam	if (ath_hal_getfatalstate(sc->sc_ah, &sp, &len)) {
1457155732Ssam		KASSERT(len >= 6*sizeof(u_int32_t), ("len %u bytes", len));
1458170530Ssam		state = sp;
1459155732Ssam		if_printf(ifp, "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n",
1460155732Ssam		    state[0], state[1] , state[2], state[3],
1461155732Ssam		    state[4], state[5]);
1462155732Ssam	}
1463138570Ssam	ath_reset(ifp);
1464116743Ssam}
1465116743Ssam
1466116743Ssamstatic void
1467178354Ssamath_bmiss_vap(struct ieee80211vap *vap)
1468178354Ssam{
1469178354Ssam	/*
1470178354Ssam	 * Workaround phantom bmiss interrupts by sanity-checking
1471178354Ssam	 * the time of our last rx'd frame.  If it is within the
1472178354Ssam	 * beacon miss interval then ignore the interrupt.  If it's
1473178354Ssam	 * truly a bmiss we'll get another interrupt soon and that'll
1474188465Ssam	 * be dispatched up for processing.  Note this applies only
1475188465Ssam	 * for h/w beacon miss events.
1476178354Ssam	 */
1477188465Ssam	if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) == 0) {
1478188465Ssam		struct ifnet *ifp = vap->iv_ic->ic_ifp;
1479188465Ssam		struct ath_softc *sc = ifp->if_softc;
1480188465Ssam		u_int64_t lastrx = sc->sc_lastrx;
1481188465Ssam		u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah);
1482188465Ssam		u_int bmisstimeout =
1483188465Ssam			vap->iv_bmissthreshold * vap->iv_bss->ni_intval * 1024;
1484188465Ssam
1485188465Ssam		DPRINTF(sc, ATH_DEBUG_BEACON,
1486188465Ssam		    "%s: tsf %llu lastrx %lld (%llu) bmiss %u\n",
1487188465Ssam		    __func__, (unsigned long long) tsf,
1488188465Ssam		    (unsigned long long)(tsf - lastrx),
1489188465Ssam		    (unsigned long long) lastrx, bmisstimeout);
1490188465Ssam
1491188465Ssam		if (tsf - lastrx <= bmisstimeout) {
1492188465Ssam			sc->sc_stats.ast_bmiss_phantom++;
1493188465Ssam			return;
1494188465Ssam		}
1495188465Ssam	}
1496188465Ssam	ATH_VAP(vap)->av_bmiss(vap);
1497178354Ssam}
1498178354Ssam
1499185480Ssamstatic int
1500185480Ssamath_hal_gethangstate(struct ath_hal *ah, uint32_t mask, uint32_t *hangs)
1501185480Ssam{
1502185480Ssam	uint32_t rsize;
1503185480Ssam	void *sp;
1504185480Ssam
1505217619Sadrian	if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS, &mask, sizeof(mask), &sp, &rsize))
1506185480Ssam		return 0;
1507185480Ssam	KASSERT(rsize == sizeof(uint32_t), ("resultsize %u", rsize));
1508185480Ssam	*hangs = *(uint32_t *)sp;
1509185480Ssam	return 1;
1510185480Ssam}
1511185480Ssam
1512178354Ssamstatic void
1513116743Ssamath_bmiss_proc(void *arg, int pending)
1514116743Ssam{
1515116743Ssam	struct ath_softc *sc = arg;
1516178354Ssam	struct ifnet *ifp = sc->sc_ifp;
1517185480Ssam	uint32_t hangs;
1518116743Ssam
1519138570Ssam	DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending);
1520185480Ssam
1521185480Ssam	if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
1522204100Sdeischen		if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs);
1523185480Ssam		ath_reset(ifp);
1524185480Ssam	} else
1525185480Ssam		ieee80211_beacon_miss(ifp->if_l2com);
1526116743Ssam}
1527116743Ssam
1528166013Ssam/*
1529178354Ssam * Handle TKIP MIC setup to deal hardware that doesn't do MIC
1530178354Ssam * calcs together with WME.  If necessary disable the crypto
1531178354Ssam * hardware and mark the 802.11 state so keys will be setup
1532178354Ssam * with the MIC work done in software.
1533178354Ssam */
1534116743Ssamstatic void
1535178354Ssamath_settkipmic(struct ath_softc *sc)
1536178354Ssam{
1537178354Ssam	struct ifnet *ifp = sc->sc_ifp;
1538178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
1539178354Ssam
1540178354Ssam	if ((ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP) && !sc->sc_wmetkipmic) {
1541178354Ssam		if (ic->ic_flags & IEEE80211_F_WME) {
1542178354Ssam			ath_hal_settkipmic(sc->sc_ah, AH_FALSE);
1543178354Ssam			ic->ic_cryptocaps &= ~IEEE80211_CRYPTO_TKIPMIC;
1544178354Ssam		} else {
1545178354Ssam			ath_hal_settkipmic(sc->sc_ah, AH_TRUE);
1546178354Ssam			ic->ic_cryptocaps |= IEEE80211_CRYPTO_TKIPMIC;
1547178354Ssam		}
1548178354Ssam	}
1549178354Ssam}
1550178354Ssam
1551178354Ssamstatic void
1552116743Ssamath_init(void *arg)
1553116743Ssam{
1554116743Ssam	struct ath_softc *sc = (struct ath_softc *) arg;
1555147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
1556178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
1557116743Ssam	struct ath_hal *ah = sc->sc_ah;
1558116743Ssam	HAL_STATUS status;
1559116743Ssam
1560138570Ssam	DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
1561138570Ssam		__func__, ifp->if_flags);
1562116743Ssam
1563121100Ssam	ATH_LOCK(sc);
1564116743Ssam	/*
1565116743Ssam	 * Stop anything previously setup.  This is safe
1566116743Ssam	 * whether this is the first time through or not.
1567116743Ssam	 */
1568138570Ssam	ath_stop_locked(ifp);
1569116743Ssam
1570116743Ssam	/*
1571116743Ssam	 * The basic interface to setting the hardware in a good
1572116743Ssam	 * state is ``reset''.  On return the hardware is known to
1573116743Ssam	 * be powered up and with interrupts disabled.  This must
1574116743Ssam	 * be followed by initialization of the appropriate bits
1575116743Ssam	 * and then setup of the interrupt mask.
1576116743Ssam	 */
1577178354Ssam	ath_settkipmic(sc);
1578187831Ssam	if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, &status)) {
1579116743Ssam		if_printf(ifp, "unable to reset hardware; hal status %u\n",
1580116743Ssam			status);
1581178354Ssam		ATH_UNLOCK(sc);
1582178354Ssam		return;
1583116743Ssam	}
1584178354Ssam	ath_chan_change(sc, ic->ic_curchan);
1585116743Ssam
1586222585Sadrian	/* Let DFS at it in case it's a DFS channel */
1587222585Sadrian	ath_dfs_radar_enable(sc, ic->ic_curchan);
1588222585Sadrian
1589116743Ssam	/*
1590148362Ssam	 * Likewise this is set during reset so update
1591148362Ssam	 * state cached in the driver.
1592148362Ssam	 */
1593148362Ssam	sc->sc_diversity = ath_hal_getdiversity(ah);
1594185744Ssam	sc->sc_lastlongcal = 0;
1595185744Ssam	sc->sc_resetcal = 1;
1596185744Ssam	sc->sc_lastcalreset = 0;
1597217684Sadrian	sc->sc_lastani = 0;
1598217684Sadrian	sc->sc_lastshortcal = 0;
1599217684Sadrian	sc->sc_doresetcal = AH_FALSE;
1600223568Sadrian	/*
1601223568Sadrian	 * Beacon timers were cleared here; give ath_newstate()
1602223568Sadrian	 * a hint that the beacon timers should be poked when
1603223568Sadrian	 * things transition to the RUN state.
1604223568Sadrian	 */
1605223568Sadrian	sc->sc_beacons = 0;
1606138570Ssam
1607138570Ssam	/*
1608116743Ssam	 * Setup the hardware after reset: the key cache
1609116743Ssam	 * is filled as needed and the receive engine is
1610116743Ssam	 * set going.  Frame transmit is handled entirely
1611116743Ssam	 * in the frame output path; there's nothing to do
1612116743Ssam	 * here except setup the interrupt mask.
1613116743Ssam	 */
1614116743Ssam	if (ath_startrecv(sc) != 0) {
1615116743Ssam		if_printf(ifp, "unable to start recv logic\n");
1616178354Ssam		ATH_UNLOCK(sc);
1617178354Ssam		return;
1618116743Ssam	}
1619116743Ssam
1620116743Ssam	/*
1621116743Ssam	 * Enable interrupts.
1622116743Ssam	 */
1623116743Ssam	sc->sc_imask = HAL_INT_RX | HAL_INT_TX
1624116743Ssam		  | HAL_INT_RXEOL | HAL_INT_RXORN
1625116743Ssam		  | HAL_INT_FATAL | HAL_INT_GLOBAL;
1626138570Ssam	/*
1627138570Ssam	 * Enable MIB interrupts when there are hardware phy counters.
1628138570Ssam	 * Note we only do this (at the moment) for station mode.
1629138570Ssam	 */
1630138570Ssam	if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA)
1631138570Ssam		sc->sc_imask |= HAL_INT_MIB;
1632116743Ssam
1633220782Sadrian	/* Enable global TX timeout and carrier sense timeout if available */
1634220772Sadrian	if (ath_hal_gtxto_supported(ah))
1635220784Sadrian		sc->sc_imask |= HAL_INT_GTT;
1636220772Sadrian
1637220779Sadrian	DPRINTF(sc, ATH_DEBUG_RESET, "%s: imask=0x%x\n",
1638220779Sadrian		__func__, sc->sc_imask);
1639220779Sadrian
1640148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
1641189605Ssam	callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc);
1642178354Ssam	ath_hal_intrset(ah, sc->sc_imask);
1643116743Ssam
1644178354Ssam	ATH_UNLOCK(sc);
1645178354Ssam
1646155486Ssam#ifdef ATH_TX99_DIAG
1647155486Ssam	if (sc->sc_tx99 != NULL)
1648155486Ssam		sc->sc_tx99->start(sc->sc_tx99);
1649155486Ssam	else
1650155486Ssam#endif
1651178354Ssam	ieee80211_start_all(ic);		/* start all vap's */
1652116743Ssam}
1653116743Ssam
1654116743Ssamstatic void
1655138570Ssamath_stop_locked(struct ifnet *ifp)
1656116743Ssam{
1657116743Ssam	struct ath_softc *sc = ifp->if_softc;
1658116743Ssam	struct ath_hal *ah = sc->sc_ah;
1659116743Ssam
1660138570Ssam	DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
1661138570Ssam		__func__, sc->sc_invalid, ifp->if_flags);
1662116743Ssam
1663138570Ssam	ATH_LOCK_ASSERT(sc);
1664148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1665116743Ssam		/*
1666116743Ssam		 * Shutdown the hardware and driver:
1667138570Ssam		 *    reset 802.11 state machine
1668138570Ssam		 *    turn off timers
1669116743Ssam		 *    disable interrupts
1670138570Ssam		 *    turn off the radio
1671116743Ssam		 *    clear transmit machinery
1672116743Ssam		 *    clear receive machinery
1673116743Ssam		 *    drain and release tx queues
1674116743Ssam		 *    reclaim beacon resources
1675116743Ssam		 *    power down hardware
1676116743Ssam		 *
1677116743Ssam		 * Note that some of this work is not possible if the
1678116743Ssam		 * hardware is gone (invalid).
1679116743Ssam		 */
1680155486Ssam#ifdef ATH_TX99_DIAG
1681155486Ssam		if (sc->sc_tx99 != NULL)
1682155486Ssam			sc->sc_tx99->stop(sc->sc_tx99);
1683155486Ssam#endif
1684189605Ssam		callout_stop(&sc->sc_wd_ch);
1685189605Ssam		sc->sc_wd_timer = 0;
1686148887Srwatson		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1687138570Ssam		if (!sc->sc_invalid) {
1688140432Ssam			if (sc->sc_softled) {
1689140432Ssam				callout_stop(&sc->sc_ledtimer);
1690140432Ssam				ath_hal_gpioset(ah, sc->sc_ledpin,
1691140432Ssam					!sc->sc_ledon);
1692140432Ssam				sc->sc_blinking = 0;
1693140432Ssam			}
1694116743Ssam			ath_hal_intrset(ah, 0);
1695138570Ssam		}
1696116743Ssam		ath_draintxq(sc);
1697138570Ssam		if (!sc->sc_invalid) {
1698116743Ssam			ath_stoprecv(sc);
1699138570Ssam			ath_hal_phydisable(ah);
1700138570Ssam		} else
1701116743Ssam			sc->sc_rxlink = NULL;
1702178354Ssam		ath_beacon_free(sc);	/* XXX not needed */
1703116743Ssam	}
1704138570Ssam}
1705138570Ssam
1706138570Ssamstatic void
1707138570Ssamath_stop(struct ifnet *ifp)
1708138570Ssam{
1709138570Ssam	struct ath_softc *sc = ifp->if_softc;
1710138570Ssam
1711138570Ssam	ATH_LOCK(sc);
1712138570Ssam	ath_stop_locked(ifp);
1713121100Ssam	ATH_UNLOCK(sc);
1714116743Ssam}
1715116743Ssam
1716116743Ssam/*
1717116743Ssam * Reset the hardware w/o losing operational state.  This is
1718116743Ssam * basically a more efficient way of doing ath_stop, ath_init,
1719116743Ssam * followed by state transitions to the current 802.11
1720138570Ssam * operational state.  Used to recover from various errors and
1721138570Ssam * to reset or reload hardware state.
1722116743Ssam */
1723219180Sadrianint
1724138570Ssamath_reset(struct ifnet *ifp)
1725116743Ssam{
1726138570Ssam	struct ath_softc *sc = ifp->if_softc;
1727178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
1728116743Ssam	struct ath_hal *ah = sc->sc_ah;
1729116743Ssam	HAL_STATUS status;
1730116743Ssam
1731116743Ssam	ath_hal_intrset(ah, 0);		/* disable interrupts */
1732116743Ssam	ath_draintxq(sc);		/* stop xmit side */
1733116743Ssam	ath_stoprecv(sc);		/* stop recv side */
1734178354Ssam	ath_settkipmic(sc);		/* configure TKIP MIC handling */
1735116743Ssam	/* NB: indicate channel change so we do a full reset */
1736187831Ssam	if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, &status))
1737116743Ssam		if_printf(ifp, "%s: unable to reset hardware; hal status %u\n",
1738116743Ssam			__func__, status);
1739148362Ssam	sc->sc_diversity = ath_hal_getdiversity(ah);
1740222585Sadrian
1741222585Sadrian	/* Let DFS at it in case it's a DFS channel */
1742222585Sadrian	ath_dfs_radar_enable(sc, ic->ic_curchan);
1743222585Sadrian
1744170530Ssam	if (ath_startrecv(sc) != 0)	/* restart recv */
1745170530Ssam		if_printf(ifp, "%s: unable to start recv logic\n", __func__);
1746138570Ssam	/*
1747138570Ssam	 * We may be doing a reset in response to an ioctl
1748138570Ssam	 * that changes the channel so update any state that
1749138570Ssam	 * might change as a result.
1750138570Ssam	 */
1751166013Ssam	ath_chan_change(sc, ic->ic_curchan);
1752193349Ssam	if (sc->sc_beacons) {		/* restart beacons */
1753190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
1754186904Ssam		if (sc->sc_tdma)
1755186904Ssam			ath_tdma_config(sc, NULL);
1756186904Ssam		else
1757186904Ssam#endif
1758193349Ssam			ath_beacon_config(sc, NULL);
1759186904Ssam	}
1760138570Ssam	ath_hal_intrset(ah, sc->sc_imask);
1761138570Ssam
1762138570Ssam	ath_start(ifp);			/* restart xmit */
1763138570Ssam	return 0;
1764116743Ssam}
1765116743Ssam
1766178354Ssamstatic int
1767178354Ssamath_reset_vap(struct ieee80211vap *vap, u_long cmd)
1768178354Ssam{
1769184349Ssam	struct ieee80211com *ic = vap->iv_ic;
1770184349Ssam	struct ifnet *ifp = ic->ic_ifp;
1771184349Ssam	struct ath_softc *sc = ifp->if_softc;
1772184349Ssam	struct ath_hal *ah = sc->sc_ah;
1773184349Ssam
1774184349Ssam	switch (cmd) {
1775184349Ssam	case IEEE80211_IOC_TXPOWER:
1776184349Ssam		/*
1777184349Ssam		 * If per-packet TPC is enabled, then we have nothing
1778184349Ssam		 * to do; otherwise we need to force the global limit.
1779184349Ssam		 * All this can happen directly; no need to reset.
1780184349Ssam		 */
1781184349Ssam		if (!ath_hal_gettpc(ah))
1782184349Ssam			ath_hal_settxpowlimit(ah, ic->ic_txpowlimit);
1783184349Ssam		return 0;
1784184349Ssam	}
1785184349Ssam	return ath_reset(ifp);
1786178354Ssam}
1787178354Ssam
1788218065Sadrianstruct ath_buf *
1789186904Ssam_ath_getbuf_locked(struct ath_softc *sc)
1790186904Ssam{
1791186904Ssam	struct ath_buf *bf;
1792186904Ssam
1793186904Ssam	ATH_TXBUF_LOCK_ASSERT(sc);
1794186904Ssam
1795186904Ssam	bf = STAILQ_FIRST(&sc->sc_txbuf);
1796186904Ssam	if (bf != NULL && (bf->bf_flags & ATH_BUF_BUSY) == 0)
1797186904Ssam		STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list);
1798186904Ssam	else
1799186904Ssam		bf = NULL;
1800186904Ssam	if (bf == NULL) {
1801186904Ssam		DPRINTF(sc, ATH_DEBUG_XMIT, "%s: %s\n", __func__,
1802186904Ssam		    STAILQ_FIRST(&sc->sc_txbuf) == NULL ?
1803186904Ssam			"out of xmit buffers" : "xmit buffer busy");
1804186904Ssam	}
1805186904Ssam	return bf;
1806186904Ssam}
1807186904Ssam
1808218065Sadrianstruct ath_buf *
1809186904Ssamath_getbuf(struct ath_softc *sc)
1810186904Ssam{
1811186904Ssam	struct ath_buf *bf;
1812186904Ssam
1813186904Ssam	ATH_TXBUF_LOCK(sc);
1814186904Ssam	bf = _ath_getbuf_locked(sc);
1815186904Ssam	if (bf == NULL) {
1816186904Ssam		struct ifnet *ifp = sc->sc_ifp;
1817186904Ssam
1818186904Ssam		DPRINTF(sc, ATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
1819186904Ssam		sc->sc_stats.ast_tx_qstop++;
1820186904Ssam		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1821186904Ssam	}
1822186904Ssam	ATH_TXBUF_UNLOCK(sc);
1823186904Ssam	return bf;
1824186904Ssam}
1825186904Ssam
1826170530Ssamstatic void
1827116743Ssamath_start(struct ifnet *ifp)
1828116743Ssam{
1829116743Ssam	struct ath_softc *sc = ifp->if_softc;
1830116743Ssam	struct ieee80211_node *ni;
1831116743Ssam	struct ath_buf *bf;
1832170530Ssam	struct mbuf *m, *next;
1833170530Ssam	ath_bufhead frags;
1834116743Ssam
1835148887Srwatson	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
1836116743Ssam		return;
1837116743Ssam	for (;;) {
1838116743Ssam		/*
1839116743Ssam		 * Grab a TX buffer and associated resources.
1840116743Ssam		 */
1841186904Ssam		bf = ath_getbuf(sc);
1842186904Ssam		if (bf == NULL)
1843116743Ssam			break;
1844178354Ssam
1845178354Ssam		IFQ_DEQUEUE(&ifp->if_snd, m);
1846116743Ssam		if (m == NULL) {
1847178354Ssam			ATH_TXBUF_LOCK(sc);
1848186904Ssam			STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
1849178354Ssam			ATH_TXBUF_UNLOCK(sc);
1850178354Ssam			break;
1851178354Ssam		}
1852178354Ssam		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1853178354Ssam		/*
1854178354Ssam		 * Check for fragmentation.  If this frame
1855178354Ssam		 * has been broken up verify we have enough
1856178354Ssam		 * buffers to send all the fragments so all
1857178354Ssam		 * go out or none...
1858178354Ssam		 */
1859190579Ssam		STAILQ_INIT(&frags);
1860204100Sdeischen		if ((m->m_flags & M_FRAG) &&
1861178354Ssam		    !ath_txfrag_setup(sc, &frags, m, ni)) {
1862178354Ssam			DPRINTF(sc, ATH_DEBUG_XMIT,
1863178354Ssam			    "%s: out of txfrag buffers\n", __func__);
1864188555Ssam			sc->sc_stats.ast_tx_nofrag++;
1865193351Ssam			ifp->if_oerrors++;
1866178354Ssam			ath_freetx(m);
1867178354Ssam			goto bad;
1868178354Ssam		}
1869190579Ssam		ifp->if_opackets++;
1870170530Ssam	nextfrag:
1871170530Ssam		/*
1872170530Ssam		 * Pass the frame to the h/w for transmission.
1873170530Ssam		 * Fragmented frames have each frag chained together
1874170530Ssam		 * with m_nextpkt.  We know there are sufficient ath_buf's
1875170530Ssam		 * to send all the frags because of work done by
1876170530Ssam		 * ath_txfrag_setup.  We leave m_nextpkt set while
1877170530Ssam		 * calling ath_tx_start so it can use it to extend the
1878170530Ssam		 * the tx duration to cover the subsequent frag and
1879170530Ssam		 * so it can reclaim all the mbufs in case of an error;
1880170530Ssam		 * ath_tx_start clears m_nextpkt once it commits to
1881170530Ssam		 * handing the frame to the hardware.
1882170530Ssam		 */
1883170530Ssam		next = m->m_nextpkt;
1884116743Ssam		if (ath_tx_start(sc, ni, bf, m)) {
1885116743Ssam	bad:
1886138570Ssam			ifp->if_oerrors++;
1887138570Ssam	reclaim:
1888170530Ssam			bf->bf_m = NULL;
1889170530Ssam			bf->bf_node = NULL;
1890121100Ssam			ATH_TXBUF_LOCK(sc);
1891186904Ssam			STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
1892170530Ssam			ath_txfrag_cleanup(sc, &frags, ni);
1893121100Ssam			ATH_TXBUF_UNLOCK(sc);
1894138570Ssam			if (ni != NULL)
1895138570Ssam				ieee80211_free_node(ni);
1896116743Ssam			continue;
1897116743Ssam		}
1898170530Ssam		if (next != NULL) {
1899170530Ssam			/*
1900170530Ssam			 * Beware of state changing between frags.
1901170530Ssam			 * XXX check sta power-save state?
1902170530Ssam			 */
1903178354Ssam			if (ni->ni_vap->iv_state != IEEE80211_S_RUN) {
1904170530Ssam				DPRINTF(sc, ATH_DEBUG_XMIT,
1905170530Ssam				    "%s: flush fragmented packet, state %s\n",
1906170530Ssam				    __func__,
1907178354Ssam				    ieee80211_state_name[ni->ni_vap->iv_state]);
1908170530Ssam				ath_freetx(next);
1909170530Ssam				goto reclaim;
1910170530Ssam			}
1911170530Ssam			m = next;
1912170530Ssam			bf = STAILQ_FIRST(&frags);
1913170530Ssam			KASSERT(bf != NULL, ("no buf for txfrag"));
1914170530Ssam			STAILQ_REMOVE_HEAD(&frags, bf_list);
1915170530Ssam			goto nextfrag;
1916170530Ssam		}
1917116743Ssam
1918189605Ssam		sc->sc_wd_timer = 5;
1919116743Ssam	}
1920116743Ssam}
1921116743Ssam
1922116743Ssamstatic int
1923116743Ssamath_media_change(struct ifnet *ifp)
1924116743Ssam{
1925178354Ssam	int error = ieee80211_media_change(ifp);
1926178354Ssam	/* NB: only the fixed rate can change and that doesn't need a reset */
1927178354Ssam	return (error == ENETRESET ? 0 : error);
1928116743Ssam}
1929116743Ssam
1930138570Ssam/*
1931138570Ssam * Block/unblock tx+rx processing while a key change is done.
1932138570Ssam * We assume the caller serializes key management operations
1933138570Ssam * so we only need to worry about synchronization with other
1934138570Ssam * uses that originate in the driver.
1935138570Ssam */
1936138570Ssamstatic void
1937178354Ssamath_key_update_begin(struct ieee80211vap *vap)
1938138570Ssam{
1939178354Ssam	struct ifnet *ifp = vap->iv_ic->ic_ifp;
1940138570Ssam	struct ath_softc *sc = ifp->if_softc;
1941138570Ssam
1942138570Ssam	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
1943178354Ssam	taskqueue_block(sc->sc_tq);
1944138570Ssam	IF_LOCK(&ifp->if_snd);		/* NB: doesn't block mgmt frames */
1945138570Ssam}
1946138570Ssam
1947138570Ssamstatic void
1948178354Ssamath_key_update_end(struct ieee80211vap *vap)
1949138570Ssam{
1950178354Ssam	struct ifnet *ifp = vap->iv_ic->ic_ifp;
1951138570Ssam	struct ath_softc *sc = ifp->if_softc;
1952138570Ssam
1953138570Ssam	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
1954138570Ssam	IF_UNLOCK(&ifp->if_snd);
1955178354Ssam	taskqueue_unblock(sc->sc_tq);
1956138570Ssam}
1957138570Ssam
1958138570Ssam/*
1959121177Ssam * Calculate the receive filter according to the
1960121177Ssam * operating mode and state:
1961121177Ssam *
1962121177Ssam * o always accept unicast, broadcast, and multicast traffic
1963178354Ssam * o accept PHY error frames when hardware doesn't have MIB support
1964184369Ssam *   to count and we need them for ANI (sta mode only until recently)
1965178354Ssam *   and we are not scanning (ANI is disabled)
1966184369Ssam *   NB: older hal's add rx filter bits out of sight and we need to
1967184369Ssam *	 blindly preserve them
1968121177Ssam * o probe request frames are accepted only when operating in
1969195618Srpaulo *   hostap, adhoc, mesh, or monitor modes
1970178354Ssam * o enable promiscuous mode
1971178354Ssam *   - when in monitor mode
1972178354Ssam *   - if interface marked PROMISC (assumes bridge setting is filtered)
1973121177Ssam * o accept beacons:
1974178354Ssam *   - when operating in station mode for collecting rssi data when
1975178354Ssam *     the station is otherwise quiet, or
1976121177Ssam *   - when operating in adhoc mode so the 802.11 layer creates
1977121177Ssam *     node table entries for peers,
1978121177Ssam *   - when scanning
1979178354Ssam *   - when doing s/w beacon miss (e.g. for ap+sta)
1980178354Ssam *   - when operating in ap mode in 11g to detect overlapping bss that
1981178354Ssam *     require protection
1982195618Srpaulo *   - when operating in mesh mode to detect neighbors
1983159940Ssam * o accept control frames:
1984159940Ssam *   - when in monitor mode
1985178354Ssam * XXX HT protection for 11n
1986121177Ssam */
1987121177Ssamstatic u_int32_t
1988170530Ssamath_calcrxfilter(struct ath_softc *sc)
1989116743Ssam{
1990147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
1991178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
1992121177Ssam	u_int32_t rfilt;
1993116743Ssam
1994184369Ssam	rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
1995184369Ssam	if (!sc->sc_needmib && !sc->sc_scanning)
1996184369Ssam		rfilt |= HAL_RX_FILTER_PHYERR;
1997119629Ssam	if (ic->ic_opmode != IEEE80211_M_STA)
1998119629Ssam		rfilt |= HAL_RX_FILTER_PROBEREQ;
1999192468Ssam	/* XXX ic->ic_monvaps != 0? */
2000178354Ssam	if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC))
2001116743Ssam		rfilt |= HAL_RX_FILTER_PROM;
2002120105Ssam	if (ic->ic_opmode == IEEE80211_M_STA ||
2003184350Ssam	    ic->ic_opmode == IEEE80211_M_IBSS ||
2004178354Ssam	    sc->sc_swbmiss || sc->sc_scanning)
2005116743Ssam		rfilt |= HAL_RX_FILTER_BEACON;
2006178354Ssam	/*
2007178354Ssam	 * NB: We don't recalculate the rx filter when
2008178354Ssam	 * ic_protmode changes; otherwise we could do
2009178354Ssam	 * this only when ic_protmode != NONE.
2010178354Ssam	 */
2011178354Ssam	if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
2012178354Ssam	    IEEE80211_IS_CHAN_ANYG(ic->ic_curchan))
2013178354Ssam		rfilt |= HAL_RX_FILTER_BEACON;
2014220029Sadrian
2015220029Sadrian	/*
2016220054Sadrian	 * Enable hardware PS-POLL RX only for hostap mode;
2017220029Sadrian	 * STA mode sends PS-POLL frames but never
2018220054Sadrian	 * receives them.
2019220029Sadrian	 */
2020221811Sadrian	if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PSPOLL,
2021220029Sadrian	    0, NULL) == HAL_OK &&
2022220029Sadrian	    ic->ic_opmode == IEEE80211_M_HOSTAP)
2023220029Sadrian		rfilt |= HAL_RX_FILTER_PSPOLL;
2024220029Sadrian
2025195807Ssam	if (sc->sc_nmeshvaps) {
2026195618Srpaulo		rfilt |= HAL_RX_FILTER_BEACON;
2027195618Srpaulo		if (sc->sc_hasbmatch)
2028195618Srpaulo			rfilt |= HAL_RX_FILTER_BSSID;
2029195618Srpaulo		else
2030195618Srpaulo			rfilt |= HAL_RX_FILTER_PROM;
2031195618Srpaulo	}
2032159940Ssam	if (ic->ic_opmode == IEEE80211_M_MONITOR)
2033159940Ssam		rfilt |= HAL_RX_FILTER_CONTROL;
2034220029Sadrian
2035222668Sadrian	if (sc->sc_dodfs) {
2036222668Sadrian		rfilt |= HAL_RX_FILTER_PHYRADAR;
2037222668Sadrian	}
2038222668Sadrian
2039220029Sadrian	/*
2040220029Sadrian	 * Enable RX of compressed BAR frames only when doing
2041220029Sadrian	 * 802.11n. Required for A-MPDU.
2042220029Sadrian	 */
2043218145Sadrian	if (IEEE80211_IS_CHAN_HT(ic->ic_curchan))
2044218145Sadrian		rfilt |= HAL_RX_FILTER_COMPBAR;
2045220029Sadrian
2046178354Ssam	DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x, %s if_flags 0x%x\n",
2047178354Ssam	    __func__, rfilt, ieee80211_opmode_name[ic->ic_opmode], ifp->if_flags);
2048121177Ssam	return rfilt;
2049121177Ssam}
2050121177Ssam
2051121177Ssamstatic void
2052178354Ssamath_update_promisc(struct ifnet *ifp)
2053121177Ssam{
2054178354Ssam	struct ath_softc *sc = ifp->if_softc;
2055178354Ssam	u_int32_t rfilt;
2056121177Ssam
2057121177Ssam	/* configure rx filter */
2058170530Ssam	rfilt = ath_calcrxfilter(sc);
2059178354Ssam	ath_hal_setrxfilter(sc->sc_ah, rfilt);
2060116743Ssam
2061178354Ssam	DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x\n", __func__, rfilt);
2062178354Ssam}
2063121177Ssam
2064178354Ssamstatic void
2065178354Ssamath_update_mcast(struct ifnet *ifp)
2066178354Ssam{
2067178354Ssam	struct ath_softc *sc = ifp->if_softc;
2068178354Ssam	u_int32_t mfilt[2];
2069138570Ssam
2070116743Ssam	/* calculate and install multicast filter */
2071116743Ssam	if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
2072178354Ssam		struct ifmultiaddr *ifma;
2073178354Ssam		/*
2074178354Ssam		 * Merge multicast addresses to form the hardware filter.
2075178354Ssam		 */
2076116743Ssam		mfilt[0] = mfilt[1] = 0;
2077195049Srwatson		if_maddr_rlock(ifp);	/* XXX need some fiddling to remove? */
2078116743Ssam		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
2079116743Ssam			caddr_t dl;
2080178354Ssam			u_int32_t val;
2081178354Ssam			u_int8_t pos;
2082116743Ssam
2083116743Ssam			/* calculate XOR of eight 6bit values */
2084116743Ssam			dl = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
2085116743Ssam			val = LE_READ_4(dl + 0);
2086116743Ssam			pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
2087116743Ssam			val = LE_READ_4(dl + 3);
2088116743Ssam			pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
2089116743Ssam			pos &= 0x3f;
2090116743Ssam			mfilt[pos / 32] |= (1 << (pos % 32));
2091116743Ssam		}
2092195049Srwatson		if_maddr_runlock(ifp);
2093178354Ssam	} else
2094116743Ssam		mfilt[0] = mfilt[1] = ~0;
2095178354Ssam	ath_hal_setmcastfilter(sc->sc_ah, mfilt[0], mfilt[1]);
2096178354Ssam	DPRINTF(sc, ATH_DEBUG_MODE, "%s: MC filter %08x:%08x\n",
2097178354Ssam		__func__, mfilt[0], mfilt[1]);
2098116743Ssam}
2099116743Ssam
2100178354Ssamstatic void
2101178354Ssamath_mode_init(struct ath_softc *sc)
2102178354Ssam{
2103178354Ssam	struct ifnet *ifp = sc->sc_ifp;
2104178354Ssam	struct ath_hal *ah = sc->sc_ah;
2105178354Ssam	u_int32_t rfilt;
2106178354Ssam
2107178354Ssam	/* configure rx filter */
2108178354Ssam	rfilt = ath_calcrxfilter(sc);
2109178354Ssam	ath_hal_setrxfilter(ah, rfilt);
2110178354Ssam
2111178354Ssam	/* configure operational mode */
2112178354Ssam	ath_hal_setopmode(ah);
2113178354Ssam
2114190526Ssam	/* handle any link-level address change */
2115190526Ssam	ath_hal_setmac(ah, IF_LLADDR(ifp));
2116178354Ssam
2117178354Ssam	/* calculate and install multicast filter */
2118178354Ssam	ath_update_mcast(ifp);
2119178354Ssam}
2120178354Ssam
2121138570Ssam/*
2122138570Ssam * Set the slot time based on the current setting.
2123138570Ssam */
2124138570Ssamstatic void
2125138570Ssamath_setslottime(struct ath_softc *sc)
2126138570Ssam{
2127178354Ssam	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
2128138570Ssam	struct ath_hal *ah = sc->sc_ah;
2129165571Ssam	u_int usec;
2130138570Ssam
2131166013Ssam	if (IEEE80211_IS_CHAN_HALF(ic->ic_curchan))
2132166013Ssam		usec = 13;
2133166013Ssam	else if (IEEE80211_IS_CHAN_QUARTER(ic->ic_curchan))
2134166013Ssam		usec = 21;
2135166013Ssam	else if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
2136166013Ssam		/* honor short/long slot time only in 11g */
2137166013Ssam		/* XXX shouldn't honor on pure g or turbo g channel */
2138166013Ssam		if (ic->ic_flags & IEEE80211_F_SHSLOT)
2139166013Ssam			usec = HAL_SLOT_TIME_9;
2140165571Ssam		else
2141166013Ssam			usec = HAL_SLOT_TIME_20;
2142166013Ssam	} else
2143165571Ssam		usec = HAL_SLOT_TIME_9;
2144165571Ssam
2145165571Ssam	DPRINTF(sc, ATH_DEBUG_RESET,
2146165571Ssam	    "%s: chan %u MHz flags 0x%x %s slot, %u usec\n",
2147165571Ssam	    __func__, ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags,
2148165571Ssam	    ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", usec);
2149165571Ssam
2150165571Ssam	ath_hal_setslottime(ah, usec);
2151138570Ssam	sc->sc_updateslot = OK;
2152138570Ssam}
2153138570Ssam
2154138570Ssam/*
2155138570Ssam * Callback from the 802.11 layer to update the
2156138570Ssam * slot time based on the current setting.
2157138570Ssam */
2158138570Ssamstatic void
2159138570Ssamath_updateslot(struct ifnet *ifp)
2160138570Ssam{
2161138570Ssam	struct ath_softc *sc = ifp->if_softc;
2162178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
2163138570Ssam
2164138570Ssam	/*
2165138570Ssam	 * When not coordinating the BSS, change the hardware
2166138570Ssam	 * immediately.  For other operation we defer the change
2167138570Ssam	 * until beacon updates have propagated to the stations.
2168138570Ssam	 */
2169195618Srpaulo	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
2170195618Srpaulo	    ic->ic_opmode == IEEE80211_M_MBSS)
2171138570Ssam		sc->sc_updateslot = UPDATE;
2172138570Ssam	else
2173138570Ssam		ath_setslottime(sc);
2174138570Ssam}
2175138570Ssam
2176138570Ssam/*
2177140433Ssam * Setup a h/w transmit queue for beacons.
2178140433Ssam */
2179140433Ssamstatic int
2180140433Ssamath_beaconq_setup(struct ath_hal *ah)
2181140433Ssam{
2182140433Ssam	HAL_TXQ_INFO qi;
2183140433Ssam
2184140433Ssam	memset(&qi, 0, sizeof(qi));
2185140433Ssam	qi.tqi_aifs = HAL_TXQ_USEDEFAULT;
2186140433Ssam	qi.tqi_cwmin = HAL_TXQ_USEDEFAULT;
2187140433Ssam	qi.tqi_cwmax = HAL_TXQ_USEDEFAULT;
2188147067Ssam	/* NB: for dynamic turbo, don't enable any other interrupts */
2189155515Ssam	qi.tqi_qflags = HAL_TXQ_TXDESCINT_ENABLE;
2190140433Ssam	return ath_hal_setuptxqueue(ah, HAL_TX_QUEUE_BEACON, &qi);
2191140433Ssam}
2192140433Ssam
2193140433Ssam/*
2194147067Ssam * Setup the transmit queue parameters for the beacon queue.
2195147067Ssam */
2196147067Ssamstatic int
2197147067Ssamath_beaconq_config(struct ath_softc *sc)
2198147067Ssam{
2199147067Ssam#define	ATH_EXPONENT_TO_VALUE(v)	((1<<(v))-1)
2200178354Ssam	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
2201147067Ssam	struct ath_hal *ah = sc->sc_ah;
2202147067Ssam	HAL_TXQ_INFO qi;
2203147067Ssam
2204147067Ssam	ath_hal_gettxqueueprops(ah, sc->sc_bhalq, &qi);
2205195618Srpaulo	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
2206195618Srpaulo	    ic->ic_opmode == IEEE80211_M_MBSS) {
2207147067Ssam		/*
2208147067Ssam		 * Always burst out beacon and CAB traffic.
2209147067Ssam		 */
2210147067Ssam		qi.tqi_aifs = ATH_BEACON_AIFS_DEFAULT;
2211147067Ssam		qi.tqi_cwmin = ATH_BEACON_CWMIN_DEFAULT;
2212147067Ssam		qi.tqi_cwmax = ATH_BEACON_CWMAX_DEFAULT;
2213147067Ssam	} else {
2214147067Ssam		struct wmeParams *wmep =
2215147067Ssam			&ic->ic_wme.wme_chanParams.cap_wmeParams[WME_AC_BE];
2216147067Ssam		/*
2217147067Ssam		 * Adhoc mode; important thing is to use 2x cwmin.
2218147067Ssam		 */
2219147067Ssam		qi.tqi_aifs = wmep->wmep_aifsn;
2220147067Ssam		qi.tqi_cwmin = 2*ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmin);
2221147067Ssam		qi.tqi_cwmax = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmax);
2222147067Ssam	}
2223147067Ssam
2224147067Ssam	if (!ath_hal_settxqueueprops(ah, sc->sc_bhalq, &qi)) {
2225147067Ssam		device_printf(sc->sc_dev, "unable to update parameters for "
2226147067Ssam			"beacon hardware queue!\n");
2227147067Ssam		return 0;
2228147067Ssam	} else {
2229147067Ssam		ath_hal_resettxqueue(ah, sc->sc_bhalq); /* push to h/w */
2230147067Ssam		return 1;
2231147067Ssam	}
2232147067Ssam#undef ATH_EXPONENT_TO_VALUE
2233147067Ssam}
2234147067Ssam
2235147067Ssam/*
2236138570Ssam * Allocate and setup an initial beacon frame.
2237138570Ssam */
2238116743Ssamstatic int
2239116743Ssamath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
2240116743Ssam{
2241178354Ssam	struct ieee80211vap *vap = ni->ni_vap;
2242178354Ssam	struct ath_vap *avp = ATH_VAP(vap);
2243116743Ssam	struct ath_buf *bf;
2244116743Ssam	struct mbuf *m;
2245138570Ssam	int error;
2246116743Ssam
2247178354Ssam	bf = avp->av_bcbuf;
2248178354Ssam	if (bf->bf_m != NULL) {
2249178354Ssam		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
2250178354Ssam		m_freem(bf->bf_m);
2251178354Ssam		bf->bf_m = NULL;
2252138570Ssam	}
2253178354Ssam	if (bf->bf_node != NULL) {
2254178354Ssam		ieee80211_free_node(bf->bf_node);
2255178354Ssam		bf->bf_node = NULL;
2256178354Ssam	}
2257178354Ssam
2258116743Ssam	/*
2259116743Ssam	 * NB: the beacon data buffer must be 32-bit aligned;
2260116743Ssam	 * we assume the mbuf routines will return us something
2261116743Ssam	 * with this alignment (perhaps should assert).
2262116743Ssam	 */
2263178354Ssam	m = ieee80211_beacon_alloc(ni, &avp->av_boff);
2264116743Ssam	if (m == NULL) {
2265178354Ssam		device_printf(sc->sc_dev, "%s: cannot get mbuf\n", __func__);
2266116743Ssam		sc->sc_stats.ast_be_nombuf++;
2267116743Ssam		return ENOMEM;
2268116743Ssam	}
2269140756Ssam	error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
2270140756Ssam				     bf->bf_segs, &bf->bf_nseg,
2271116743Ssam				     BUS_DMA_NOWAIT);
2272178354Ssam	if (error != 0) {
2273178354Ssam		device_printf(sc->sc_dev,
2274178354Ssam		    "%s: cannot map mbuf, bus_dmamap_load_mbuf_sg returns %d\n",
2275178354Ssam		    __func__, error);
2276116743Ssam		m_freem(m);
2277178354Ssam		return error;
2278116743Ssam	}
2279178354Ssam
2280178354Ssam	/*
2281178354Ssam	 * Calculate a TSF adjustment factor required for staggered
2282178354Ssam	 * beacons.  Note that we assume the format of the beacon
2283178354Ssam	 * frame leaves the tstamp field immediately following the
2284178354Ssam	 * header.
2285178354Ssam	 */
2286178354Ssam	if (sc->sc_stagbeacons && avp->av_bslot > 0) {
2287178354Ssam		uint64_t tsfadjust;
2288178354Ssam		struct ieee80211_frame *wh;
2289178354Ssam
2290178354Ssam		/*
2291178354Ssam		 * The beacon interval is in TU's; the TSF is in usecs.
2292178354Ssam		 * We figure out how many TU's to add to align the timestamp
2293178354Ssam		 * then convert to TSF units and handle byte swapping before
2294178354Ssam		 * inserting it in the frame.  The hardware will then add this
2295178354Ssam		 * each time a beacon frame is sent.  Note that we align vap's
2296178354Ssam		 * 1..N and leave vap 0 untouched.  This means vap 0 has a
2297178354Ssam		 * timestamp in one beacon interval while the others get a
2298178354Ssam		 * timstamp aligned to the next interval.
2299178354Ssam		 */
2300178354Ssam		tsfadjust = ni->ni_intval *
2301178354Ssam		    (ATH_BCBUF - avp->av_bslot) / ATH_BCBUF;
2302178354Ssam		tsfadjust = htole64(tsfadjust << 10);	/* TU -> TSF */
2303178354Ssam
2304178354Ssam		DPRINTF(sc, ATH_DEBUG_BEACON,
2305178354Ssam		    "%s: %s beacons bslot %d intval %u tsfadjust %llu\n",
2306178354Ssam		    __func__, sc->sc_stagbeacons ? "stagger" : "burst",
2307183222Ssam		    avp->av_bslot, ni->ni_intval,
2308183222Ssam		    (long long unsigned) le64toh(tsfadjust));
2309178354Ssam
2310178354Ssam		wh = mtod(m, struct ieee80211_frame *);
2311178354Ssam		memcpy(&wh[1], &tsfadjust, sizeof(tsfadjust));
2312178354Ssam	}
2313178354Ssam	bf->bf_m = m;
2314178354Ssam	bf->bf_node = ieee80211_ref_node(ni);
2315178354Ssam
2316178354Ssam	return 0;
2317138570Ssam}
2318116743Ssam
2319138570Ssam/*
2320138570Ssam * Setup the beacon frame for transmit.
2321138570Ssam */
2322138570Ssamstatic void
2323138570Ssamath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf)
2324138570Ssam{
2325138570Ssam#define	USE_SHPREAMBLE(_ic) \
2326138570Ssam	(((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
2327138570Ssam		== IEEE80211_F_SHPREAMBLE)
2328138570Ssam	struct ieee80211_node *ni = bf->bf_node;
2329138570Ssam	struct ieee80211com *ic = ni->ni_ic;
2330138570Ssam	struct mbuf *m = bf->bf_m;
2331138570Ssam	struct ath_hal *ah = sc->sc_ah;
2332138570Ssam	struct ath_desc *ds;
2333138570Ssam	int flags, antenna;
2334155477Ssam	const HAL_RATE_TABLE *rt;
2335155477Ssam	u_int8_t rix, rate;
2336138570Ssam
2337157798Ssam	DPRINTF(sc, ATH_DEBUG_BEACON_PROC, "%s: m %p len %u\n",
2338138570Ssam		__func__, m, m->m_len);
2339138570Ssam
2340116743Ssam	/* setup descriptors */
2341116743Ssam	ds = bf->bf_desc;
2342116743Ssam
2343138570Ssam	flags = HAL_TXDESC_NOACK;
2344138570Ssam	if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) {
2345138570Ssam		ds->ds_link = bf->bf_daddr;	/* self-linked */
2346138570Ssam		flags |= HAL_TXDESC_VEOL;
2347138570Ssam		/*
2348138570Ssam		 * Let hardware handle antenna switching.
2349138570Ssam		 */
2350148326Ssam		antenna = sc->sc_txantenna;
2351138570Ssam	} else {
2352138570Ssam		ds->ds_link = 0;
2353138570Ssam		/*
2354138570Ssam		 * Switch antenna every 4 beacons.
2355138570Ssam		 * XXX assumes two antenna
2356138570Ssam		 */
2357178354Ssam		if (sc->sc_txantenna != 0)
2358178354Ssam			antenna = sc->sc_txantenna;
2359178354Ssam		else if (sc->sc_stagbeacons && sc->sc_nbcnvaps != 0)
2360178354Ssam			antenna = ((sc->sc_stats.ast_be_xmit / sc->sc_nbcnvaps) & 4 ? 2 : 1);
2361178354Ssam		else
2362178354Ssam			antenna = (sc->sc_stats.ast_be_xmit & 4 ? 2 : 1);
2363138570Ssam	}
2364138570Ssam
2365138570Ssam	KASSERT(bf->bf_nseg == 1,
2366138570Ssam		("multi-segment beacon frame; nseg %u", bf->bf_nseg));
2367116743Ssam	ds->ds_data = bf->bf_segs[0].ds_addr;
2368116743Ssam	/*
2369116743Ssam	 * Calculate rate code.
2370116743Ssam	 * XXX everything at min xmit rate
2371116743Ssam	 */
2372178354Ssam	rix = 0;
2373155477Ssam	rt = sc->sc_currates;
2374155477Ssam	rate = rt->info[rix].rateCode;
2375138570Ssam	if (USE_SHPREAMBLE(ic))
2376155477Ssam		rate |= rt->info[rix].shortPreamble;
2377116743Ssam	ath_hal_setuptxdesc(ah, ds
2378138570Ssam		, m->m_len + IEEE80211_CRC_LEN	/* frame length */
2379138570Ssam		, sizeof(struct ieee80211_frame)/* header length */
2380116743Ssam		, HAL_PKT_TYPE_BEACON		/* Atheros packet type */
2381138570Ssam		, ni->ni_txpower		/* txpower XXX */
2382116743Ssam		, rate, 1			/* series 0 rate/tries */
2383116743Ssam		, HAL_TXKEYIX_INVALID		/* no encryption */
2384138570Ssam		, antenna			/* antenna mode */
2385138570Ssam		, flags				/* no ack, veol for beacons */
2386116743Ssam		, 0				/* rts/cts rate */
2387116743Ssam		, 0				/* rts/cts duration */
2388116743Ssam	);
2389116743Ssam	/* NB: beacon's BufLen must be a multiple of 4 bytes */
2390116743Ssam	ath_hal_filltxdesc(ah, ds
2391138570Ssam		, roundup(m->m_len, 4)		/* buffer length */
2392138570Ssam		, AH_TRUE			/* first segment */
2393138570Ssam		, AH_TRUE			/* last segment */
2394138570Ssam		, ds				/* first descriptor */
2395116743Ssam	);
2396178354Ssam#if 0
2397178354Ssam	ath_desc_swap(ds);
2398178354Ssam#endif
2399138570Ssam#undef USE_SHPREAMBLE
2400116743Ssam}
2401116743Ssam
2402172211Ssamstatic void
2403178354Ssamath_beacon_update(struct ieee80211vap *vap, int item)
2404172211Ssam{
2405178354Ssam	struct ieee80211_beacon_offsets *bo = &ATH_VAP(vap)->av_boff;
2406172211Ssam
2407172211Ssam	setbit(bo->bo_flags, item);
2408172211Ssam}
2409172211Ssam
2410138570Ssam/*
2411159938Ssam * Append the contents of src to dst; both queues
2412159938Ssam * are assumed to be locked.
2413159938Ssam */
2414159938Ssamstatic void
2415159938Ssamath_txqmove(struct ath_txq *dst, struct ath_txq *src)
2416159938Ssam{
2417159938Ssam	STAILQ_CONCAT(&dst->axq_q, &src->axq_q);
2418159938Ssam	dst->axq_link = src->axq_link;
2419159938Ssam	src->axq_link = NULL;
2420159938Ssam	dst->axq_depth += src->axq_depth;
2421159938Ssam	src->axq_depth = 0;
2422159938Ssam}
2423159938Ssam
2424159938Ssam/*
2425138570Ssam * Transmit a beacon frame at SWBA.  Dynamic updates to the
2426138570Ssam * frame contents are done as needed and the slot time is
2427138570Ssam * also adjusted based on current state.
2428138570Ssam */
2429116743Ssamstatic void
2430116743Ssamath_beacon_proc(void *arg, int pending)
2431116743Ssam{
2432116743Ssam	struct ath_softc *sc = arg;
2433116743Ssam	struct ath_hal *ah = sc->sc_ah;
2434178354Ssam	struct ieee80211vap *vap;
2435178354Ssam	struct ath_buf *bf;
2436178354Ssam	int slot, otherant;
2437178354Ssam	uint32_t bfaddr;
2438116743Ssam
2439138570Ssam	DPRINTF(sc, ATH_DEBUG_BEACON_PROC, "%s: pending %u\n",
2440138570Ssam		__func__, pending);
2441138570Ssam	/*
2442138570Ssam	 * Check if the previous beacon has gone out.  If
2443155730Ssam	 * not don't try to post another, skip this period
2444155730Ssam	 * and wait for the next.  Missed beacons indicate
2445155730Ssam	 * a problem and should not occur.  If we miss too
2446155730Ssam	 * many consecutive beacons reset the device.
2447138570Ssam	 */
2448138570Ssam	if (ath_hal_numtxpending(ah, sc->sc_bhalq) != 0) {
2449138570Ssam		sc->sc_bmisscount++;
2450211299Sadrian		sc->sc_stats.ast_be_missed++;
2451157798Ssam		DPRINTF(sc, ATH_DEBUG_BEACON,
2452138570Ssam			"%s: missed %u consecutive beacons\n",
2453138570Ssam			__func__, sc->sc_bmisscount);
2454188446Ssam		if (sc->sc_bmisscount >= ath_bstuck_threshold)
2455155491Ssam			taskqueue_enqueue(sc->sc_tq, &sc->sc_bstucktask);
2456138570Ssam		return;
2457138570Ssam	}
2458138570Ssam	if (sc->sc_bmisscount != 0) {
2459138570Ssam		DPRINTF(sc, ATH_DEBUG_BEACON,
2460138570Ssam			"%s: resume beacon xmit after %u misses\n",
2461138570Ssam			__func__, sc->sc_bmisscount);
2462138570Ssam		sc->sc_bmisscount = 0;
2463138570Ssam	}
2464138570Ssam
2465178354Ssam	if (sc->sc_stagbeacons) {			/* staggered beacons */
2466178354Ssam		struct ieee80211com *ic = sc->sc_ifp->if_l2com;
2467178354Ssam		uint32_t tsftu;
2468178354Ssam
2469178354Ssam		tsftu = ath_hal_gettsf32(ah) >> 10;
2470178354Ssam		/* XXX lintval */
2471178354Ssam		slot = ((tsftu % ic->ic_lintval) * ATH_BCBUF) / ic->ic_lintval;
2472178354Ssam		vap = sc->sc_bslot[(slot+1) % ATH_BCBUF];
2473178354Ssam		bfaddr = 0;
2474193389Ssam		if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) {
2475178354Ssam			bf = ath_beacon_generate(sc, vap);
2476178354Ssam			if (bf != NULL)
2477178354Ssam				bfaddr = bf->bf_daddr;
2478138570Ssam		}
2479178354Ssam	} else {					/* burst'd beacons */
2480178354Ssam		uint32_t *bflink = &bfaddr;
2481178354Ssam
2482178354Ssam		for (slot = 0; slot < ATH_BCBUF; slot++) {
2483178354Ssam			vap = sc->sc_bslot[slot];
2484193389Ssam			if (vap != NULL && vap->iv_state >= IEEE80211_S_RUN) {
2485178354Ssam				bf = ath_beacon_generate(sc, vap);
2486178354Ssam				if (bf != NULL) {
2487178354Ssam					*bflink = bf->bf_daddr;
2488178354Ssam					bflink = &bf->bf_desc->ds_link;
2489178354Ssam				}
2490178354Ssam			}
2491178354Ssam		}
2492178354Ssam		*bflink = 0;				/* terminate list */
2493138570Ssam	}
2494138570Ssam
2495138570Ssam	/*
2496138570Ssam	 * Handle slot time change when a non-ERP station joins/leaves
2497138570Ssam	 * an 11g network.  The 802.11 layer notifies us via callback,
2498138570Ssam	 * we mark updateslot, then wait one beacon before effecting
2499138570Ssam	 * the change.  This gives associated stations at least one
2500138570Ssam	 * beacon interval to note the state change.
2501138570Ssam	 */
2502138570Ssam	/* XXX locking */
2503178354Ssam	if (sc->sc_updateslot == UPDATE) {
2504138570Ssam		sc->sc_updateslot = COMMIT;	/* commit next beacon */
2505178354Ssam		sc->sc_slotupdate = slot;
2506178354Ssam	} else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot)
2507138570Ssam		ath_setslottime(sc);		/* commit change to h/w */
2508138570Ssam
2509138570Ssam	/*
2510138570Ssam	 * Check recent per-antenna transmit statistics and flip
2511138570Ssam	 * the default antenna if noticeably more frames went out
2512138570Ssam	 * on the non-default antenna.
2513138570Ssam	 * XXX assumes 2 anntenae
2514138570Ssam	 */
2515178354Ssam	if (!sc->sc_diversity && (!sc->sc_stagbeacons || slot == 0)) {
2516178354Ssam		otherant = sc->sc_defant & 1 ? 2 : 1;
2517178354Ssam		if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] + 2)
2518178354Ssam			ath_setdefantenna(sc, otherant);
2519178354Ssam		sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0;
2520178354Ssam	}
2521138570Ssam
2522178354Ssam	if (bfaddr != 0) {
2523178354Ssam		/*
2524178354Ssam		 * Stop any current dma and put the new frame on the queue.
2525178354Ssam		 * This should never fail since we check above that no frames
2526178354Ssam		 * are still pending on the queue.
2527178354Ssam		 */
2528178354Ssam		if (!ath_hal_stoptxdma(ah, sc->sc_bhalq)) {
2529178354Ssam			DPRINTF(sc, ATH_DEBUG_ANY,
2530178354Ssam				"%s: beacon queue %u did not stop?\n",
2531178354Ssam				__func__, sc->sc_bhalq);
2532178354Ssam		}
2533178354Ssam		/* NB: cabq traffic should already be queued and primed */
2534178354Ssam		ath_hal_puttxbuf(ah, sc->sc_bhalq, bfaddr);
2535178354Ssam		ath_hal_txstart(ah, sc->sc_bhalq);
2536138570Ssam
2537178354Ssam		sc->sc_stats.ast_be_xmit++;
2538178354Ssam	}
2539178354Ssam}
2540178354Ssam
2541178354Ssamstatic struct ath_buf *
2542178354Ssamath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap)
2543178354Ssam{
2544178354Ssam	struct ath_vap *avp = ATH_VAP(vap);
2545178354Ssam	struct ath_txq *cabq = sc->sc_cabq;
2546178354Ssam	struct ath_buf *bf;
2547178354Ssam	struct mbuf *m;
2548178354Ssam	int nmcastq, error;
2549178354Ssam
2550193389Ssam	KASSERT(vap->iv_state >= IEEE80211_S_RUN,
2551178354Ssam	    ("not running, state %d", vap->iv_state));
2552178354Ssam	KASSERT(avp->av_bcbuf != NULL, ("no beacon buffer"));
2553178354Ssam
2554138570Ssam	/*
2555178354Ssam	 * Update dynamic beacon contents.  If this returns
2556178354Ssam	 * non-zero then we need to remap the memory because
2557178354Ssam	 * the beacon frame changed size (probably because
2558178354Ssam	 * of the TIM bitmap).
2559138570Ssam	 */
2560178354Ssam	bf = avp->av_bcbuf;
2561178354Ssam	m = bf->bf_m;
2562178354Ssam	nmcastq = avp->av_mcastq.axq_depth;
2563178354Ssam	if (ieee80211_beacon_update(bf->bf_node, &avp->av_boff, m, nmcastq)) {
2564178354Ssam		/* XXX too conservative? */
2565178354Ssam		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
2566178354Ssam		error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
2567178354Ssam					     bf->bf_segs, &bf->bf_nseg,
2568178354Ssam					     BUS_DMA_NOWAIT);
2569178354Ssam		if (error != 0) {
2570178354Ssam			if_printf(vap->iv_ifp,
2571178354Ssam			    "%s: bus_dmamap_load_mbuf_sg failed, error %u\n",
2572178354Ssam			    __func__, error);
2573178354Ssam			return NULL;
2574178354Ssam		}
2575116743Ssam	}
2576178354Ssam	if ((avp->av_boff.bo_tim[4] & 1) && cabq->axq_depth) {
2577178354Ssam		DPRINTF(sc, ATH_DEBUG_BEACON,
2578178354Ssam		    "%s: cabq did not drain, mcastq %u cabq %u\n",
2579178354Ssam		    __func__, nmcastq, cabq->axq_depth);
2580178354Ssam		sc->sc_stats.ast_cabq_busy++;
2581178354Ssam		if (sc->sc_nvaps > 1 && sc->sc_stagbeacons) {
2582178354Ssam			/*
2583178354Ssam			 * CABQ traffic from a previous vap is still pending.
2584178354Ssam			 * We must drain the q before this beacon frame goes
2585178354Ssam			 * out as otherwise this vap's stations will get cab
2586178354Ssam			 * frames from a different vap.
2587178354Ssam			 * XXX could be slow causing us to miss DBA
2588178354Ssam			 */
2589178354Ssam			ath_tx_draintxq(sc, cabq);
2590178354Ssam		}
2591178354Ssam	}
2592178354Ssam	ath_beacon_setup(sc, bf);
2593116743Ssam	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
2594116743Ssam
2595138570Ssam	/*
2596138570Ssam	 * Enable the CAB queue before the beacon queue to
2597138570Ssam	 * insure cab frames are triggered by this beacon.
2598138570Ssam	 */
2599178354Ssam	if (avp->av_boff.bo_tim[4] & 1) {
2600178354Ssam		struct ath_hal *ah = sc->sc_ah;
2601178354Ssam
2602160692Ssam		/* NB: only at DTIM */
2603159938Ssam		ATH_TXQ_LOCK(cabq);
2604178354Ssam		ATH_TXQ_LOCK(&avp->av_mcastq);
2605159938Ssam		if (nmcastq) {
2606159938Ssam			struct ath_buf *bfm;
2607159938Ssam
2608159938Ssam			/*
2609159938Ssam			 * Move frames from the s/w mcast q to the h/w cab q.
2610178354Ssam			 * XXX MORE_DATA bit
2611159938Ssam			 */
2612178354Ssam			bfm = STAILQ_FIRST(&avp->av_mcastq.axq_q);
2613159938Ssam			if (cabq->axq_link != NULL) {
2614159938Ssam				*cabq->axq_link = bfm->bf_daddr;
2615159938Ssam			} else
2616159938Ssam				ath_hal_puttxbuf(ah, cabq->axq_qnum,
2617159938Ssam					bfm->bf_daddr);
2618178354Ssam			ath_txqmove(cabq, &avp->av_mcastq);
2619159938Ssam
2620159938Ssam			sc->sc_stats.ast_cabq_xmit += nmcastq;
2621159938Ssam		}
2622159938Ssam		/* NB: gated by beacon so safe to start here */
2623159938Ssam		ath_hal_txstart(ah, cabq->axq_qnum);
2624159938Ssam		ATH_TXQ_UNLOCK(cabq);
2625178354Ssam		ATH_TXQ_UNLOCK(&avp->av_mcastq);
2626159938Ssam	}
2627178354Ssam	return bf;
2628178354Ssam}
2629178354Ssam
2630178354Ssamstatic void
2631178354Ssamath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap)
2632178354Ssam{
2633178354Ssam	struct ath_vap *avp = ATH_VAP(vap);
2634178354Ssam	struct ath_hal *ah = sc->sc_ah;
2635178354Ssam	struct ath_buf *bf;
2636178354Ssam	struct mbuf *m;
2637178354Ssam	int error;
2638178354Ssam
2639178354Ssam	KASSERT(avp->av_bcbuf != NULL, ("no beacon buffer"));
2640178354Ssam
2641178354Ssam	/*
2642178354Ssam	 * Update dynamic beacon contents.  If this returns
2643178354Ssam	 * non-zero then we need to remap the memory because
2644178354Ssam	 * the beacon frame changed size (probably because
2645178354Ssam	 * of the TIM bitmap).
2646178354Ssam	 */
2647178354Ssam	bf = avp->av_bcbuf;
2648178354Ssam	m = bf->bf_m;
2649178354Ssam	if (ieee80211_beacon_update(bf->bf_node, &avp->av_boff, m, 0)) {
2650178354Ssam		/* XXX too conservative? */
2651178354Ssam		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
2652178354Ssam		error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
2653178354Ssam					     bf->bf_segs, &bf->bf_nseg,
2654178354Ssam					     BUS_DMA_NOWAIT);
2655178354Ssam		if (error != 0) {
2656178354Ssam			if_printf(vap->iv_ifp,
2657178354Ssam			    "%s: bus_dmamap_load_mbuf_sg failed, error %u\n",
2658178354Ssam			    __func__, error);
2659178354Ssam			return;
2660178354Ssam		}
2661178354Ssam	}
2662178354Ssam	ath_beacon_setup(sc, bf);
2663178354Ssam	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
2664178354Ssam
2665178354Ssam	/* NB: caller is known to have already stopped tx dma */
2666116743Ssam	ath_hal_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr);
2667116743Ssam	ath_hal_txstart(ah, sc->sc_bhalq);
2668116743Ssam}
2669116743Ssam
2670138570Ssam/*
2671138570Ssam * Reset the hardware after detecting beacons have stopped.
2672138570Ssam */
2673116743Ssamstatic void
2674138570Ssamath_bstuck_proc(void *arg, int pending)
2675138570Ssam{
2676138570Ssam	struct ath_softc *sc = arg;
2677147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
2678138570Ssam
2679138570Ssam	if_printf(ifp, "stuck beacon; resetting (bmiss count %u)\n",
2680138570Ssam		sc->sc_bmisscount);
2681188269Ssam	sc->sc_stats.ast_bstuck++;
2682138570Ssam	ath_reset(ifp);
2683138570Ssam}
2684138570Ssam
2685138570Ssam/*
2686178354Ssam * Reclaim beacon resources and return buffer to the pool.
2687178354Ssam */
2688178354Ssamstatic void
2689178354Ssamath_beacon_return(struct ath_softc *sc, struct ath_buf *bf)
2690178354Ssam{
2691178354Ssam
2692178354Ssam	if (bf->bf_m != NULL) {
2693178354Ssam		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
2694178354Ssam		m_freem(bf->bf_m);
2695178354Ssam		bf->bf_m = NULL;
2696178354Ssam	}
2697178354Ssam	if (bf->bf_node != NULL) {
2698178354Ssam		ieee80211_free_node(bf->bf_node);
2699178354Ssam		bf->bf_node = NULL;
2700178354Ssam	}
2701178354Ssam	STAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list);
2702178354Ssam}
2703178354Ssam
2704178354Ssam/*
2705138570Ssam * Reclaim beacon resources.
2706138570Ssam */
2707138570Ssamstatic void
2708116743Ssamath_beacon_free(struct ath_softc *sc)
2709116743Ssam{
2710138570Ssam	struct ath_buf *bf;
2711116743Ssam
2712140759Ssam	STAILQ_FOREACH(bf, &sc->sc_bbuf, bf_list) {
2713138570Ssam		if (bf->bf_m != NULL) {
2714138570Ssam			bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
2715138570Ssam			m_freem(bf->bf_m);
2716138570Ssam			bf->bf_m = NULL;
2717140759Ssam		}
2718140759Ssam		if (bf->bf_node != NULL) {
2719140759Ssam			ieee80211_free_node(bf->bf_node);
2720138570Ssam			bf->bf_node = NULL;
2721138570Ssam		}
2722140759Ssam	}
2723116743Ssam}
2724116743Ssam
2725116743Ssam/*
2726116743Ssam * Configure the beacon and sleep timers.
2727116743Ssam *
2728116743Ssam * When operating as an AP this resets the TSF and sets
2729116743Ssam * up the hardware to notify us when we need to issue beacons.
2730116743Ssam *
2731116743Ssam * When operating in station mode this sets up the beacon
2732116743Ssam * timers according to the timestamp of the last received
2733116743Ssam * beacon and the current TSF, configures PCF and DTIM
2734116743Ssam * handling, programs the sleep registers so the hardware
2735116743Ssam * will wakeup in time to receive beacons, and configures
2736116743Ssam * the beacon miss handling so we'll receive a BMISS
2737116743Ssam * interrupt when we stop seeing beacons from the AP
2738116743Ssam * we've associated with.
2739116743Ssam */
2740116743Ssamstatic void
2741178354Ssamath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
2742116743Ssam{
2743155496Ssam#define	TSF_TO_TU(_h,_l) \
2744155496Ssam	((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
2745155496Ssam#define	FUDGE	2
2746116743Ssam	struct ath_hal *ah = sc->sc_ah;
2747178354Ssam	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
2748178354Ssam	struct ieee80211_node *ni;
2749155496Ssam	u_int32_t nexttbtt, intval, tsftu;
2750155496Ssam	u_int64_t tsf;
2751116743Ssam
2752178354Ssam	if (vap == NULL)
2753178354Ssam		vap = TAILQ_FIRST(&ic->ic_vaps);	/* XXX */
2754178354Ssam	ni = vap->iv_bss;
2755178354Ssam
2756147153Ssam	/* extract tstamp from last beacon and convert to TU */
2757147153Ssam	nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4),
2758147153Ssam			     LE_READ_4(ni->ni_tstamp.data));
2759195618Srpaulo	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
2760195618Srpaulo	    ic->ic_opmode == IEEE80211_M_MBSS) {
2761178354Ssam		/*
2762195618Srpaulo		 * For multi-bss ap/mesh support beacons are either staggered
2763178354Ssam		 * evenly over N slots or burst together.  For the former
2764178354Ssam		 * arrange for the SWBA to be delivered for each slot.
2765178354Ssam		 * Slots that are not occupied will generate nothing.
2766178354Ssam		 */
2767178354Ssam		/* NB: the beacon interval is kept internally in TU's */
2768178354Ssam		intval = ni->ni_intval & HAL_BEACON_PERIOD;
2769178354Ssam		if (sc->sc_stagbeacons)
2770178354Ssam			intval /= ATH_BCBUF;
2771178354Ssam	} else {
2772178354Ssam		/* NB: the beacon interval is kept internally in TU's */
2773178354Ssam		intval = ni->ni_intval & HAL_BEACON_PERIOD;
2774178354Ssam	}
2775139498Ssam	if (nexttbtt == 0)		/* e.g. for ap mode */
2776139498Ssam		nexttbtt = intval;
2777139498Ssam	else if (intval)		/* NB: can be 0 for monitor mode */
2778139498Ssam		nexttbtt = roundup(nexttbtt, intval);
2779139498Ssam	DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
2780139498Ssam		__func__, nexttbtt, intval, ni->ni_intval);
2781178354Ssam	if (ic->ic_opmode == IEEE80211_M_STA && !sc->sc_swbmiss) {
2782116743Ssam		HAL_BEACON_STATE bs;
2783147153Ssam		int dtimperiod, dtimcount;
2784147153Ssam		int cfpperiod, cfpcount;
2785116743Ssam
2786147153Ssam		/*
2787147153Ssam		 * Setup dtim and cfp parameters according to
2788147153Ssam		 * last beacon we received (which may be none).
2789147153Ssam		 */
2790147153Ssam		dtimperiod = ni->ni_dtim_period;
2791147153Ssam		if (dtimperiod <= 0)		/* NB: 0 if not known */
2792147153Ssam			dtimperiod = 1;
2793147153Ssam		dtimcount = ni->ni_dtim_count;
2794147153Ssam		if (dtimcount >= dtimperiod)	/* NB: sanity check */
2795147153Ssam			dtimcount = 0;		/* XXX? */
2796147153Ssam		cfpperiod = 1;			/* NB: no PCF support yet */
2797147153Ssam		cfpcount = 0;
2798147153Ssam		/*
2799147153Ssam		 * Pull nexttbtt forward to reflect the current
2800147153Ssam		 * TSF and calculate dtim+cfp state for the result.
2801147153Ssam		 */
2802147153Ssam		tsf = ath_hal_gettsf64(ah);
2803155496Ssam		tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
2804147153Ssam		do {
2805147153Ssam			nexttbtt += intval;
2806147153Ssam			if (--dtimcount < 0) {
2807147153Ssam				dtimcount = dtimperiod - 1;
2808147153Ssam				if (--cfpcount < 0)
2809147153Ssam					cfpcount = cfpperiod - 1;
2810147153Ssam			}
2811147153Ssam		} while (nexttbtt < tsftu);
2812116743Ssam		memset(&bs, 0, sizeof(bs));
2813139498Ssam		bs.bs_intval = intval;
2814116743Ssam		bs.bs_nexttbtt = nexttbtt;
2815147153Ssam		bs.bs_dtimperiod = dtimperiod*intval;
2816147153Ssam		bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
2817147153Ssam		bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
2818147153Ssam		bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
2819147153Ssam		bs.bs_cfpmaxduration = 0;
2820147153Ssam#if 0
2821116743Ssam		/*
2822138570Ssam		 * The 802.11 layer records the offset to the DTIM
2823138570Ssam		 * bitmap while receiving beacons; use it here to
2824138570Ssam		 * enable h/w detection of our AID being marked in
2825138570Ssam		 * the bitmap vector (to indicate frames for us are
2826138570Ssam		 * pending at the AP).
2827147153Ssam		 * XXX do DTIM handling in s/w to WAR old h/w bugs
2828147153Ssam		 * XXX enable based on h/w rev for newer chips
2829138570Ssam		 */
2830138570Ssam		bs.bs_timoffset = ni->ni_timoff;
2831147153Ssam#endif
2832138570Ssam		/*
2833116743Ssam		 * Calculate the number of consecutive beacons to miss
2834170530Ssam		 * before taking a BMISS interrupt.
2835116743Ssam		 * Note that we clamp the result to at most 10 beacons.
2836116743Ssam		 */
2837178354Ssam		bs.bs_bmissthreshold = vap->iv_bmissthreshold;
2838116743Ssam		if (bs.bs_bmissthreshold > 10)
2839116743Ssam			bs.bs_bmissthreshold = 10;
2840116743Ssam		else if (bs.bs_bmissthreshold <= 0)
2841116743Ssam			bs.bs_bmissthreshold = 1;
2842116743Ssam
2843116743Ssam		/*
2844116743Ssam		 * Calculate sleep duration.  The configuration is
2845116743Ssam		 * given in ms.  We insure a multiple of the beacon
2846116743Ssam		 * period is used.  Also, if the sleep duration is
2847116743Ssam		 * greater than the DTIM period then it makes senses
2848116743Ssam		 * to make it a multiple of that.
2849116743Ssam		 *
2850116743Ssam		 * XXX fixed at 100ms
2851116743Ssam		 */
2852140755Ssam		bs.bs_sleepduration =
2853140755Ssam			roundup(IEEE80211_MS_TO_TU(100), bs.bs_intval);
2854116743Ssam		if (bs.bs_sleepduration > bs.bs_dtimperiod)
2855116743Ssam			bs.bs_sleepduration = roundup(bs.bs_sleepduration, bs.bs_dtimperiod);
2856116743Ssam
2857170530Ssam		DPRINTF(sc, ATH_DEBUG_BEACON,
2858147153Ssam			"%s: tsf %ju tsf:tu %u intval %u nexttbtt %u dtim %u nextdtim %u bmiss %u sleep %u cfp:period %u maxdur %u next %u timoffset %u\n"
2859116743Ssam			, __func__
2860147153Ssam			, tsf, tsftu
2861116743Ssam			, bs.bs_intval
2862116743Ssam			, bs.bs_nexttbtt
2863116743Ssam			, bs.bs_dtimperiod
2864116743Ssam			, bs.bs_nextdtim
2865116743Ssam			, bs.bs_bmissthreshold
2866116743Ssam			, bs.bs_sleepduration
2867138570Ssam			, bs.bs_cfpperiod
2868138570Ssam			, bs.bs_cfpmaxduration
2869138570Ssam			, bs.bs_cfpnext
2870138570Ssam			, bs.bs_timoffset
2871138570Ssam		);
2872116743Ssam		ath_hal_intrset(ah, 0);
2873138570Ssam		ath_hal_beacontimers(ah, &bs);
2874116743Ssam		sc->sc_imask |= HAL_INT_BMISS;
2875116743Ssam		ath_hal_intrset(ah, sc->sc_imask);
2876116743Ssam	} else {
2877116743Ssam		ath_hal_intrset(ah, 0);
2878139498Ssam		if (nexttbtt == intval)
2879138570Ssam			intval |= HAL_BEACON_RESET_TSF;
2880138570Ssam		if (ic->ic_opmode == IEEE80211_M_IBSS) {
2881138570Ssam			/*
2882138570Ssam			 * In IBSS mode enable the beacon timers but only
2883138570Ssam			 * enable SWBA interrupts if we need to manually
2884138570Ssam			 * prepare beacon frames.  Otherwise we use a
2885138570Ssam			 * self-linked tx descriptor and let the hardware
2886138570Ssam			 * deal with things.
2887138570Ssam			 */
2888138570Ssam			intval |= HAL_BEACON_ENA;
2889138570Ssam			if (!sc->sc_hasveol)
2890138570Ssam				sc->sc_imask |= HAL_INT_SWBA;
2891155496Ssam			if ((intval & HAL_BEACON_RESET_TSF) == 0) {
2892155496Ssam				/*
2893155496Ssam				 * Pull nexttbtt forward to reflect
2894155496Ssam				 * the current TSF.
2895155496Ssam				 */
2896155496Ssam				tsf = ath_hal_gettsf64(ah);
2897155496Ssam				tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
2898155496Ssam				do {
2899155496Ssam					nexttbtt += intval;
2900155496Ssam				} while (nexttbtt < tsftu);
2901155496Ssam			}
2902147067Ssam			ath_beaconq_config(sc);
2903195618Srpaulo		} else if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
2904195618Srpaulo		    ic->ic_opmode == IEEE80211_M_MBSS) {
2905138570Ssam			/*
2906195618Srpaulo			 * In AP/mesh mode we enable the beacon timers
2907195618Srpaulo			 * and SWBA interrupts to prepare beacon frames.
2908138570Ssam			 */
2909138570Ssam			intval |= HAL_BEACON_ENA;
2910118342Ssam			sc->sc_imask |= HAL_INT_SWBA;	/* beacon prepare */
2911147067Ssam			ath_beaconq_config(sc);
2912138570Ssam		}
2913138570Ssam		ath_hal_beaconinit(ah, nexttbtt, intval);
2914138570Ssam		sc->sc_bmisscount = 0;
2915116743Ssam		ath_hal_intrset(ah, sc->sc_imask);
2916138570Ssam		/*
2917138570Ssam		 * When using a self-linked beacon descriptor in
2918138570Ssam		 * ibss mode load it once here.
2919138570Ssam		 */
2920138570Ssam		if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol)
2921178354Ssam			ath_beacon_start_adhoc(sc, vap);
2922116743Ssam	}
2923155496Ssam	sc->sc_syncbeacon = 0;
2924155496Ssam#undef FUDGE
2925147153Ssam#undef TSF_TO_TU
2926116743Ssam}
2927116743Ssam
2928116743Ssamstatic void
2929116743Ssamath_load_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
2930116743Ssam{
2931116743Ssam	bus_addr_t *paddr = (bus_addr_t*) arg;
2932139496Ssam	KASSERT(error == 0, ("error %u on bus_dma callback", error));
2933116743Ssam	*paddr = segs->ds_addr;
2934116743Ssam}
2935116743Ssam
2936116743Ssamstatic int
2937138570Ssamath_descdma_setup(struct ath_softc *sc,
2938138570Ssam	struct ath_descdma *dd, ath_bufhead *head,
2939138570Ssam	const char *name, int nbuf, int ndesc)
2940116743Ssam{
2941138570Ssam#define	DS2PHYS(_dd, _ds) \
2942138570Ssam	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
2943224541Sadrian#define	ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \
2944224541Sadrian	((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0)
2945147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
2946224541Sadrian	uint8_t *ds;
2947116743Ssam	struct ath_buf *bf;
2948138570Ssam	int i, bsize, error;
2949224541Sadrian	int desc_len;
2950116743Ssam
2951224541Sadrian	desc_len = sizeof(struct ath_desc);
2952224541Sadrian
2953138570Ssam	DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA: %u buffers %u desc/buf\n",
2954138570Ssam	    __func__, name, nbuf, ndesc);
2955138570Ssam
2956138570Ssam	dd->dd_name = name;
2957224541Sadrian	dd->dd_desc_len = desc_len * nbuf * ndesc;
2958138570Ssam
2959138570Ssam	/*
2960224541Sadrian	 * Merlin work-around:
2961224541Sadrian	 * Descriptors that cross the 4KB boundary can't be used.
2962224541Sadrian	 * Assume one skipped descriptor per 4KB page.
2963224541Sadrian	 */
2964224541Sadrian	if (! ath_hal_split4ktrans(sc->sc_ah)) {
2965224541Sadrian		int numdescpage = 4096 / (desc_len * ndesc);
2966224541Sadrian		dd->dd_desc_len = (nbuf / numdescpage + 1) * 4096;
2967224541Sadrian	}
2968224541Sadrian
2969224541Sadrian	/*
2970138570Ssam	 * Setup DMA descriptor area.
2971138570Ssam	 */
2972166165Smarius	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
2973138570Ssam		       PAGE_SIZE, 0,		/* alignment, bounds */
2974138570Ssam		       BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
2975138570Ssam		       BUS_SPACE_MAXADDR,	/* highaddr */
2976138570Ssam		       NULL, NULL,		/* filter, filterarg */
2977138570Ssam		       dd->dd_desc_len,		/* maxsize */
2978138570Ssam		       1,			/* nsegments */
2979158366Ssam		       dd->dd_desc_len,		/* maxsegsize */
2980138570Ssam		       BUS_DMA_ALLOCNOW,	/* flags */
2981138570Ssam		       NULL,			/* lockfunc */
2982138570Ssam		       NULL,			/* lockarg */
2983138570Ssam		       &dd->dd_dmat);
2984138570Ssam	if (error != 0) {
2985138570Ssam		if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
2986116743Ssam		return error;
2987138570Ssam	}
2988116743Ssam
2989138570Ssam	/* allocate descriptors */
2990138570Ssam	error = bus_dmamap_create(dd->dd_dmat, BUS_DMA_NOWAIT, &dd->dd_dmamap);
2991138570Ssam	if (error != 0) {
2992138570Ssam		if_printf(ifp, "unable to create dmamap for %s descriptors, "
2993138570Ssam			"error %u\n", dd->dd_name, error);
2994116743Ssam		goto fail0;
2995138570Ssam	}
2996116743Ssam
2997138570Ssam	error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc,
2998204100Sdeischen				 BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
2999164598Ssam				 &dd->dd_dmamap);
3000138570Ssam	if (error != 0) {
3001138570Ssam		if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
3002138570Ssam			"error %u\n", nbuf * ndesc, dd->dd_name, error);
3003116743Ssam		goto fail1;
3004138570Ssam	}
3005116743Ssam
3006138570Ssam	error = bus_dmamap_load(dd->dd_dmat, dd->dd_dmamap,
3007138570Ssam				dd->dd_desc, dd->dd_desc_len,
3008138570Ssam				ath_load_cb, &dd->dd_desc_paddr,
3009138570Ssam				BUS_DMA_NOWAIT);
3010138570Ssam	if (error != 0) {
3011138570Ssam		if_printf(ifp, "unable to map %s descriptors, error %u\n",
3012138570Ssam			dd->dd_name, error);
3013116743Ssam		goto fail2;
3014138570Ssam	}
3015116743Ssam
3016224541Sadrian	ds = (uint8_t *) dd->dd_desc;
3017138570Ssam	DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA map: %p (%lu) -> %p (%lu)\n",
3018138570Ssam	    __func__, dd->dd_name, ds, (u_long) dd->dd_desc_len,
3019138570Ssam	    (caddr_t) dd->dd_desc_paddr, /*XXX*/ (u_long) dd->dd_desc_len);
3020138570Ssam
3021156073Ssam	/* allocate rx buffers */
3022138570Ssam	bsize = sizeof(struct ath_buf) * nbuf;
3023138570Ssam	bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO);
3024138570Ssam	if (bf == NULL) {
3025138570Ssam		if_printf(ifp, "malloc of %s buffers failed, size %u\n",
3026138570Ssam			dd->dd_name, bsize);
3027138570Ssam		goto fail3;
3028116743Ssam	}
3029138570Ssam	dd->dd_bufptr = bf;
3030116743Ssam
3031138570Ssam	STAILQ_INIT(head);
3032224541Sadrian	for (i = 0; i < nbuf; i++, bf++, ds += (ndesc * desc_len)) {
3033224541Sadrian		bf->bf_desc = (struct ath_desc *) ds;
3034138570Ssam		bf->bf_daddr = DS2PHYS(dd, ds);
3035224541Sadrian		if (! ath_hal_split4ktrans(sc->sc_ah)) {
3036224541Sadrian			/*
3037224541Sadrian			 * Merlin WAR: Skip descriptor addresses which
3038224541Sadrian			 * cause 4KB boundary crossing along any point
3039224541Sadrian			 * in the descriptor.
3040224541Sadrian			 */
3041224541Sadrian			 if (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr,
3042224541Sadrian			     desc_len * ndesc)) {
3043224541Sadrian				/* Start at the next page */
3044224541Sadrian				ds += 0x1000 - (bf->bf_daddr & 0xFFF);
3045224541Sadrian				bf->bf_desc = (struct ath_desc *) ds;
3046224541Sadrian				bf->bf_daddr = DS2PHYS(dd, ds);
3047224541Sadrian			}
3048224541Sadrian		}
3049116743Ssam		error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
3050138570Ssam				&bf->bf_dmamap);
3051138570Ssam		if (error != 0) {
3052138570Ssam			if_printf(ifp, "unable to create dmamap for %s "
3053138570Ssam				"buffer %u, error %u\n", dd->dd_name, i, error);
3054138570Ssam			ath_descdma_cleanup(sc, dd, head);
3055138570Ssam			return error;
3056138570Ssam		}
3057138570Ssam		STAILQ_INSERT_TAIL(head, bf, bf_list);
3058116743Ssam	}
3059116743Ssam	return 0;
3060138570Ssamfail3:
3061138570Ssam	bus_dmamap_unload(dd->dd_dmat, dd->dd_dmamap);
3062116743Ssamfail2:
3063138570Ssam	bus_dmamem_free(dd->dd_dmat, dd->dd_desc, dd->dd_dmamap);
3064116743Ssamfail1:
3065138570Ssam	bus_dmamap_destroy(dd->dd_dmat, dd->dd_dmamap);
3066116743Ssamfail0:
3067138570Ssam	bus_dma_tag_destroy(dd->dd_dmat);
3068138570Ssam	memset(dd, 0, sizeof(*dd));
3069116743Ssam	return error;
3070138570Ssam#undef DS2PHYS
3071224541Sadrian#undef ATH_DESC_4KB_BOUND_CHECK
3072116743Ssam}
3073116743Ssam
3074116743Ssamstatic void
3075138570Ssamath_descdma_cleanup(struct ath_softc *sc,
3076138570Ssam	struct ath_descdma *dd, ath_bufhead *head)
3077116743Ssam{
3078116743Ssam	struct ath_buf *bf;
3079138570Ssam	struct ieee80211_node *ni;
3080116743Ssam
3081138570Ssam	bus_dmamap_unload(dd->dd_dmat, dd->dd_dmamap);
3082138570Ssam	bus_dmamem_free(dd->dd_dmat, dd->dd_desc, dd->dd_dmamap);
3083138570Ssam	bus_dmamap_destroy(dd->dd_dmat, dd->dd_dmamap);
3084138570Ssam	bus_dma_tag_destroy(dd->dd_dmat);
3085116743Ssam
3086138570Ssam	STAILQ_FOREACH(bf, head, bf_list) {
3087116743Ssam		if (bf->bf_m) {
3088116743Ssam			m_freem(bf->bf_m);
3089116743Ssam			bf->bf_m = NULL;
3090116743Ssam		}
3091138570Ssam		if (bf->bf_dmamap != NULL) {
3092138570Ssam			bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
3093138570Ssam			bf->bf_dmamap = NULL;
3094138570Ssam		}
3095138570Ssam		ni = bf->bf_node;
3096138570Ssam		bf->bf_node = NULL;
3097138570Ssam		if (ni != NULL) {
3098138570Ssam			/*
3099138570Ssam			 * Reclaim node reference.
3100138570Ssam			 */
3101138570Ssam			ieee80211_free_node(ni);
3102138570Ssam		}
3103116743Ssam	}
3104138570Ssam
3105138570Ssam	STAILQ_INIT(head);
3106138570Ssam	free(dd->dd_bufptr, M_ATHDEV);
3107138570Ssam	memset(dd, 0, sizeof(*dd));
3108138570Ssam}
3109138570Ssam
3110138570Ssamstatic int
3111138570Ssamath_desc_alloc(struct ath_softc *sc)
3112138570Ssam{
3113138570Ssam	int error;
3114138570Ssam
3115138570Ssam	error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf,
3116155481Ssam			"rx", ath_rxbuf, 1);
3117138570Ssam	if (error != 0)
3118138570Ssam		return error;
3119138570Ssam
3120138570Ssam	error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf,
3121155481Ssam			"tx", ath_txbuf, ATH_TXDESC);
3122138570Ssam	if (error != 0) {
3123138570Ssam		ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
3124138570Ssam		return error;
3125116743Ssam	}
3126116743Ssam
3127138570Ssam	error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf,
3128178354Ssam			"beacon", ATH_BCBUF, 1);
3129138570Ssam	if (error != 0) {
3130138570Ssam		ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
3131138570Ssam		ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
3132138570Ssam		return error;
3133138570Ssam	}
3134138570Ssam	return 0;
3135116743Ssam}
3136116743Ssam
3137138570Ssamstatic void
3138138570Ssamath_desc_free(struct ath_softc *sc)
3139138570Ssam{
3140138570Ssam
3141138570Ssam	if (sc->sc_bdma.dd_desc_len != 0)
3142138570Ssam		ath_descdma_cleanup(sc, &sc->sc_bdma, &sc->sc_bbuf);
3143138570Ssam	if (sc->sc_txdma.dd_desc_len != 0)
3144138570Ssam		ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
3145138570Ssam	if (sc->sc_rxdma.dd_desc_len != 0)
3146138570Ssam		ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
3147138570Ssam}
3148138570Ssam
3149116743Ssamstatic struct ieee80211_node *
3150179643Ssamath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
3151116743Ssam{
3152179643Ssam	struct ieee80211com *ic = vap->iv_ic;
3153138570Ssam	struct ath_softc *sc = ic->ic_ifp->if_softc;
3154138570Ssam	const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
3155138570Ssam	struct ath_node *an;
3156138570Ssam
3157138570Ssam	an = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
3158138570Ssam	if (an == NULL) {
3159138570Ssam		/* XXX stat+msg */
3160120105Ssam		return NULL;
3161138570Ssam	}
3162138570Ssam	ath_rate_node_init(sc, an);
3163138570Ssam
3164138570Ssam	DPRINTF(sc, ATH_DEBUG_NODE, "%s: an %p\n", __func__, an);
3165138570Ssam	return &an->an_node;
3166116743Ssam}
3167116743Ssam
3168116743Ssamstatic void
3169138570Ssamath_node_free(struct ieee80211_node *ni)
3170116743Ssam{
3171138570Ssam	struct ieee80211com *ic = ni->ni_ic;
3172138570Ssam        struct ath_softc *sc = ic->ic_ifp->if_softc;
3173127782Ssam
3174138570Ssam	DPRINTF(sc, ATH_DEBUG_NODE, "%s: ni %p\n", __func__, ni);
3175138570Ssam
3176138570Ssam	ath_rate_node_cleanup(sc, ATH_NODE(ni));
3177138570Ssam	sc->sc_node_free(ni);
3178116743Ssam}
3179116743Ssam
3180170530Ssamstatic void
3181170530Ssamath_node_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
3182170530Ssam{
3183170530Ssam	struct ieee80211com *ic = ni->ni_ic;
3184170530Ssam	struct ath_softc *sc = ic->ic_ifp->if_softc;
3185170530Ssam	struct ath_hal *ah = sc->sc_ah;
3186170530Ssam
3187178354Ssam	*rssi = ic->ic_node_getrssi(ni);
3188187831Ssam	if (ni->ni_chan != IEEE80211_CHAN_ANYC)
3189187831Ssam		*noise = ath_hal_getchannoise(ah, ni->ni_chan);
3190187831Ssam	else
3191170530Ssam		*noise = -95;		/* nominally correct */
3192170530Ssam}
3193170530Ssam
3194116743Ssamstatic int
3195116743Ssamath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
3196116743Ssam{
3197116743Ssam	struct ath_hal *ah = sc->sc_ah;
3198116743Ssam	int error;
3199116743Ssam	struct mbuf *m;
3200116743Ssam	struct ath_desc *ds;
3201116743Ssam
3202116743Ssam	m = bf->bf_m;
3203116743Ssam	if (m == NULL) {
3204116743Ssam		/*
3205116743Ssam		 * NB: by assigning a page to the rx dma buffer we
3206116743Ssam		 * implicitly satisfy the Atheros requirement that
3207116743Ssam		 * this buffer be cache-line-aligned and sized to be
3208116743Ssam		 * multiple of the cache line size.  Not doing this
3209116743Ssam		 * causes weird stuff to happen (for the 5210 at least).
3210116743Ssam		 */
3211116743Ssam		m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
3212116743Ssam		if (m == NULL) {
3213138570Ssam			DPRINTF(sc, ATH_DEBUG_ANY,
3214138570Ssam				"%s: no mbuf/cluster\n", __func__);
3215116743Ssam			sc->sc_stats.ast_rx_nombuf++;
3216116743Ssam			return ENOMEM;
3217116743Ssam		}
3218116743Ssam		m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
3219116743Ssam
3220140756Ssam		error = bus_dmamap_load_mbuf_sg(sc->sc_dmat,
3221138570Ssam					     bf->bf_dmamap, m,
3222140756Ssam					     bf->bf_segs, &bf->bf_nseg,
3223116743Ssam					     BUS_DMA_NOWAIT);
3224116743Ssam		if (error != 0) {
3225138570Ssam			DPRINTF(sc, ATH_DEBUG_ANY,
3226140756Ssam			    "%s: bus_dmamap_load_mbuf_sg failed; error %d\n",
3227140756Ssam			    __func__, error);
3228116743Ssam			sc->sc_stats.ast_rx_busdma++;
3229155497Ssam			m_freem(m);
3230116743Ssam			return error;
3231116743Ssam		}
3232139496Ssam		KASSERT(bf->bf_nseg == 1,
3233139496Ssam			("multi-segment packet; nseg %u", bf->bf_nseg));
3234155497Ssam		bf->bf_m = m;
3235116743Ssam	}
3236116743Ssam	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREREAD);
3237116743Ssam
3238121322Ssam	/*
3239121322Ssam	 * Setup descriptors.  For receive we always terminate
3240121322Ssam	 * the descriptor list with a self-linked entry so we'll
3241121322Ssam	 * not get overrun under high load (as can happen with a
3242138570Ssam	 * 5212 when ANI processing enables PHY error frames).
3243121322Ssam	 *
3244121322Ssam	 * To insure the last descriptor is self-linked we create
3245121322Ssam	 * each descriptor as self-linked and add it to the end.  As
3246121322Ssam	 * each additional descriptor is added the previous self-linked
3247121322Ssam	 * entry is ``fixed'' naturally.  This should be safe even
3248121322Ssam	 * if DMA is happening.  When processing RX interrupts we
3249121322Ssam	 * never remove/process the last, self-linked, entry on the
3250121322Ssam	 * descriptor list.  This insures the hardware always has
3251121322Ssam	 * someplace to write a new frame.
3252121322Ssam	 */
3253220324Sadrian	/*
3254220324Sadrian	 * 11N: we can no longer afford to self link the last descriptor.
3255220324Sadrian	 * MAC acknowledges BA status as long as it copies frames to host
3256220324Sadrian	 * buffer (or rx fifo). This can incorrectly acknowledge packets
3257220324Sadrian	 * to a sender if last desc is self-linked.
3258220324Sadrian	 */
3259116743Ssam	ds = bf->bf_desc;
3260220324Sadrian	if (sc->sc_rxslink)
3261220324Sadrian		ds->ds_link = bf->bf_daddr;	/* link to self */
3262220324Sadrian	else
3263220324Sadrian		ds->ds_link = 0;		/* terminate the list */
3264116743Ssam	ds->ds_data = bf->bf_segs[0].ds_addr;
3265116743Ssam	ath_hal_setuprxdesc(ah, ds
3266116743Ssam		, m->m_len		/* buffer size */
3267116743Ssam		, 0
3268116743Ssam	);
3269116743Ssam
3270116743Ssam	if (sc->sc_rxlink != NULL)
3271116743Ssam		*sc->sc_rxlink = bf->bf_daddr;
3272116743Ssam	sc->sc_rxlink = &ds->ds_link;
3273116743Ssam	return 0;
3274116743Ssam}
3275116743Ssam
3276138570Ssam/*
3277144309Ssam * Extend 15-bit time stamp from rx descriptor to
3278154140Ssam * a full 64-bit TSF using the specified TSF.
3279144309Ssam */
3280144309Ssamstatic __inline u_int64_t
3281225444Sadrianath_extend_tsf15(u_int32_t rstamp, u_int64_t tsf)
3282144309Ssam{
3283144309Ssam	if ((tsf & 0x7fff) < rstamp)
3284144309Ssam		tsf -= 0x8000;
3285225444Sadrian
3286144309Ssam	return ((tsf &~ 0x7fff) | rstamp);
3287144309Ssam}
3288144309Ssam
3289144309Ssam/*
3290225444Sadrian * Extend 32-bit time stamp from rx descriptor to
3291225444Sadrian * a full 64-bit TSF using the specified TSF.
3292225444Sadrian */
3293225444Sadrianstatic __inline u_int64_t
3294225444Sadrianath_extend_tsf32(u_int32_t rstamp, u_int64_t tsf)
3295225444Sadrian{
3296225444Sadrian	u_int32_t tsf_low = tsf & 0xffffffff;
3297225444Sadrian	u_int64_t tsf64 = (tsf & ~0xffffffffULL) | rstamp;
3298225444Sadrian
3299225444Sadrian	if (rstamp > tsf_low && (rstamp - tsf_low > 0x10000000))
3300225444Sadrian		tsf64 -= 0x100000000ULL;
3301225444Sadrian
3302225444Sadrian	if (rstamp < tsf_low && (tsf_low - rstamp > 0x10000000))
3303225444Sadrian		tsf64 += 0x100000000ULL;
3304225444Sadrian
3305225444Sadrian	return tsf64;
3306225444Sadrian}
3307225444Sadrian
3308225444Sadrian/*
3309225444Sadrian * Extend the TSF from the RX descriptor to a full 64 bit TSF.
3310225444Sadrian * Earlier hardware versions only wrote the low 15 bits of the
3311225444Sadrian * TSF into the RX descriptor; later versions (AR5416 and up)
3312225444Sadrian * include the 32 bit TSF value.
3313225444Sadrian */
3314225444Sadrianstatic __inline u_int64_t
3315225444Sadrianath_extend_tsf(struct ath_softc *sc, u_int32_t rstamp, u_int64_t tsf)
3316225444Sadrian{
3317225444Sadrian	if (sc->sc_rxtsf32)
3318225444Sadrian		return ath_extend_tsf32(rstamp, tsf);
3319225444Sadrian	else
3320225444Sadrian		return ath_extend_tsf15(rstamp, tsf);
3321225444Sadrian}
3322225444Sadrian
3323225444Sadrian/*
3324138570Ssam * Intercept management frames to collect beacon rssi data
3325138570Ssam * and to do ibss merges.
3326138570Ssam */
3327116743Ssamstatic void
3328178354Ssamath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
3329192468Ssam	int subtype, int rssi, int nf)
3330138570Ssam{
3331178354Ssam	struct ieee80211vap *vap = ni->ni_vap;
3332178354Ssam	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
3333138570Ssam
3334138570Ssam	/*
3335138570Ssam	 * Call up first so subsequent work can use information
3336138570Ssam	 * potentially stored in the node (e.g. for ibss merge).
3337138570Ssam	 */
3338192468Ssam	ATH_VAP(vap)->av_recv_mgmt(ni, m, subtype, rssi, nf);
3339138570Ssam	switch (subtype) {
3340138570Ssam	case IEEE80211_FC0_SUBTYPE_BEACON:
3341138570Ssam		/* update rssi statistics for use by the hal */
3342155485Ssam		ATH_RSSI_LPF(sc->sc_halstats.ns_avgbrssi, rssi);
3343155496Ssam		if (sc->sc_syncbeacon &&
3344178354Ssam		    ni == vap->iv_bss && vap->iv_state == IEEE80211_S_RUN) {
3345155496Ssam			/*
3346155496Ssam			 * Resync beacon timers using the tsf of the beacon
3347155496Ssam			 * frame we just received.
3348155496Ssam			 */
3349178354Ssam			ath_beacon_config(sc, vap);
3350155496Ssam		}
3351138570Ssam		/* fall thru... */
3352138570Ssam	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
3353178354Ssam		if (vap->iv_opmode == IEEE80211_M_IBSS &&
3354178354Ssam		    vap->iv_state == IEEE80211_S_RUN) {
3355209156Sbschmidt			uint32_t rstamp = sc->sc_lastrs->rs_tstamp;
3356225444Sadrian			uint64_t tsf = ath_extend_tsf(sc, rstamp,
3357154140Ssam				ath_hal_gettsf64(sc->sc_ah));
3358138570Ssam			/*
3359138570Ssam			 * Handle ibss merge as needed; check the tsf on the
3360138570Ssam			 * frame before attempting the merge.  The 802.11 spec
3361138570Ssam			 * says the station should change it's bssid to match
3362138570Ssam			 * the oldest station with the same ssid, where oldest
3363140759Ssam			 * is determined by the tsf.  Note that hardware
3364140759Ssam			 * reconfiguration happens through callback to
3365144309Ssam			 * ath_newstate as the state machine will go from
3366144309Ssam			 * RUN -> RUN when this happens.
3367138570Ssam			 */
3368144309Ssam			if (le64toh(ni->ni_tstamp.tsf) >= tsf) {
3369144309Ssam				DPRINTF(sc, ATH_DEBUG_STATE,
3370144315Savatar				    "ibss merge, rstamp %u tsf %ju "
3371144315Savatar				    "tstamp %ju\n", rstamp, (uintmax_t)tsf,
3372144315Savatar				    (uintmax_t)ni->ni_tstamp.tsf);
3373148306Ssam				(void) ieee80211_ibss_merge(ni);
3374144309Ssam			}
3375138570Ssam		}
3376138570Ssam		break;
3377138570Ssam	}
3378138570Ssam}
3379138570Ssam
3380138570Ssam/*
3381138570Ssam * Set the default antenna.
3382138570Ssam */
3383138570Ssamstatic void
3384138570Ssamath_setdefantenna(struct ath_softc *sc, u_int antenna)
3385138570Ssam{
3386138570Ssam	struct ath_hal *ah = sc->sc_ah;
3387138570Ssam
3388138570Ssam	/* XXX block beacon interrupts */
3389138570Ssam	ath_hal_setdefantenna(ah, antenna);
3390138570Ssam	if (sc->sc_defant != antenna)
3391138570Ssam		sc->sc_stats.ast_ant_defswitch++;
3392138570Ssam	sc->sc_defant = antenna;
3393138570Ssam	sc->sc_rxotherant = 0;
3394138570Ssam}
3395138570Ssam
3396192468Ssamstatic void
3397178354Ssamath_rx_tap(struct ifnet *ifp, struct mbuf *m,
3398165185Ssam	const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
3399154140Ssam{
3400179402Ssam#define	CHAN_HT20	htole32(IEEE80211_CHAN_HT20)
3401179402Ssam#define	CHAN_HT40U	htole32(IEEE80211_CHAN_HT40U)
3402179402Ssam#define	CHAN_HT40D	htole32(IEEE80211_CHAN_HT40D)
3403184368Ssam#define	CHAN_HT		(CHAN_HT20|CHAN_HT40U|CHAN_HT40D)
3404178354Ssam	struct ath_softc *sc = ifp->if_softc;
3405184368Ssam	const HAL_RATE_TABLE *rt;
3406184368Ssam	uint8_t rix;
3407154140Ssam
3408184368Ssam	rt = sc->sc_currates;
3409184368Ssam	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
3410184368Ssam	rix = rt->rateCodeToIndex[rs->rs_rate];
3411170530Ssam	sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate;
3412154140Ssam	sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags;
3413184368Ssam#ifdef AH_SUPPORT_AR5416
3414179402Ssam	sc->sc_rx_th.wr_chan_flags &= ~CHAN_HT;
3415184368Ssam	if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) {	/* HT rate */
3416187831Ssam		struct ieee80211com *ic = ifp->if_l2com;
3417187831Ssam
3418179402Ssam		if ((rs->rs_flags & HAL_RX_2040) == 0)
3419179402Ssam			sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
3420187831Ssam		else if (IEEE80211_IS_CHAN_HT40U(ic->ic_curchan))
3421179402Ssam			sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U;
3422179402Ssam		else
3423179402Ssam			sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D;
3424179402Ssam		if ((rs->rs_flags & HAL_RX_GI) == 0)
3425179402Ssam			sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
3426170530Ssam	}
3427170530Ssam#endif
3428225444Sadrian	sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(sc, rs->rs_tstamp, tsf));
3429165185Ssam	if (rs->rs_status & HAL_RXERR_CRC)
3430154140Ssam		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
3431154140Ssam	/* XXX propagate other error flags from descriptor */
3432154140Ssam	sc->sc_rx_th.wr_antnoise = nf;
3433192468Ssam	sc->sc_rx_th.wr_antsignal = nf + rs->rs_rssi;
3434165185Ssam	sc->sc_rx_th.wr_antenna = rs->rs_antenna;
3435184368Ssam#undef CHAN_HT
3436179402Ssam#undef CHAN_HT20
3437179402Ssam#undef CHAN_HT40U
3438179402Ssam#undef CHAN_HT40D
3439154140Ssam}
3440154140Ssam
3441138570Ssamstatic void
3442178354Ssamath_handle_micerror(struct ieee80211com *ic,
3443178354Ssam	struct ieee80211_frame *wh, int keyix)
3444178354Ssam{
3445178354Ssam	struct ieee80211_node *ni;
3446178354Ssam
3447178354Ssam	/* XXX recheck MIC to deal w/ chips that lie */
3448178354Ssam	/* XXX discard MIC errors on !data frames */
3449178354Ssam	ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) wh);
3450178354Ssam	if (ni != NULL) {
3451178354Ssam		ieee80211_notify_michael_failure(ni->ni_vap, wh, keyix);
3452178354Ssam		ieee80211_free_node(ni);
3453178354Ssam	}
3454178354Ssam}
3455178354Ssam
3456178354Ssamstatic void
3457116743Ssamath_rx_proc(void *arg, int npending)
3458116743Ssam{
3459123044Ssam#define	PA2DESC(_sc, _pa) \
3460138570Ssam	((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
3461138570Ssam		((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
3462116743Ssam	struct ath_softc *sc = arg;
3463116743Ssam	struct ath_buf *bf;
3464147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
3465178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
3466116743Ssam	struct ath_hal *ah = sc->sc_ah;
3467116743Ssam	struct ath_desc *ds;
3468165185Ssam	struct ath_rx_status *rs;
3469116743Ssam	struct mbuf *m;
3470119150Ssam	struct ieee80211_node *ni;
3471155492Ssam	int len, type, ngood;
3472116743Ssam	HAL_STATUS status;
3473154140Ssam	int16_t nf;
3474154140Ssam	u_int64_t tsf;
3475116743Ssam
3476138570Ssam	DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
3477155492Ssam	ngood = 0;
3478187831Ssam	nf = ath_hal_getchannoise(ah, sc->sc_curchan);
3479184358Ssam	sc->sc_stats.ast_rx_noise = nf;
3480154140Ssam	tsf = ath_hal_gettsf64(ah);
3481116743Ssam	do {
3482138570Ssam		bf = STAILQ_FIRST(&sc->sc_rxbuf);
3483220324Sadrian		if (sc->sc_rxslink && bf == NULL) {	/* NB: shouldn't happen */
3484138570Ssam			if_printf(ifp, "%s: no buffer!\n", __func__);
3485116743Ssam			break;
3486220324Sadrian		} else if (bf == NULL) {
3487220324Sadrian			/*
3488220324Sadrian			 * End of List:
3489220324Sadrian			 * this can happen for non-self-linked RX chains
3490220324Sadrian			 */
3491220324Sadrian			sc->sc_stats.ast_rx_hitqueueend++;
3492220324Sadrian			break;
3493116743Ssam		}
3494155497Ssam		m = bf->bf_m;
3495155497Ssam		if (m == NULL) {		/* NB: shouldn't happen */
3496155497Ssam			/*
3497155497Ssam			 * If mbuf allocation failed previously there
3498155497Ssam			 * will be no mbuf; try again to re-populate it.
3499204100Sdeischen			 */
3500155497Ssam			/* XXX make debug msg */
3501155497Ssam			if_printf(ifp, "%s: no mbuf!\n", __func__);
3502155497Ssam			STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
3503155497Ssam			goto rx_next;
3504155497Ssam		}
3505121322Ssam		ds = bf->bf_desc;
3506121322Ssam		if (ds->ds_link == bf->bf_daddr) {
3507121322Ssam			/* NB: never process the self-linked entry at the end */
3508220132Sadrian			sc->sc_stats.ast_rx_hitqueueend++;
3509121322Ssam			break;
3510121322Ssam		}
3511123044Ssam		/* XXX sync descriptor memory */
3512123044Ssam		/*
3513123044Ssam		 * Must provide the virtual address of the current
3514123044Ssam		 * descriptor, the physical address, and the virtual
3515123044Ssam		 * address of the next descriptor in the h/w chain.
3516123044Ssam		 * This allows the HAL to look ahead to see if the
3517123044Ssam		 * hardware is done with a descriptor by checking the
3518123044Ssam		 * done bit in the following descriptor and the address
3519123044Ssam		 * of the current descriptor the DMA engine is working
3520123044Ssam		 * on.  All this is necessary because of our use of
3521123044Ssam		 * a self-linked list to avoid rx overruns.
3522123044Ssam		 */
3523165185Ssam		rs = &bf->bf_status.ds_rxstat;
3524123044Ssam		status = ath_hal_rxprocdesc(ah, ds,
3525165185Ssam				bf->bf_daddr, PA2DESC(sc, ds->ds_link), rs);
3526157438Ssam#ifdef ATH_DEBUG
3527138570Ssam		if (sc->sc_debug & ATH_DEBUG_RECV_DESC)
3528185243Ssam			ath_printrxbuf(sc, bf, 0, status == HAL_OK);
3529116743Ssam#endif
3530116743Ssam		if (status == HAL_EINPROGRESS)
3531116743Ssam			break;
3532138570Ssam		STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
3533218689Sadrian
3534218689Sadrian		/* These aren't specifically errors */
3535218689Sadrian		if (rs->rs_flags & HAL_RX_GI)
3536218689Sadrian			sc->sc_stats.ast_rx_halfgi++;
3537218689Sadrian		if (rs->rs_flags & HAL_RX_2040)
3538218689Sadrian			sc->sc_stats.ast_rx_2040++;
3539218689Sadrian		if (rs->rs_flags & HAL_RX_DELIM_CRC_PRE)
3540218689Sadrian			sc->sc_stats.ast_rx_pre_crc_err++;
3541218689Sadrian		if (rs->rs_flags & HAL_RX_DELIM_CRC_POST)
3542218689Sadrian			sc->sc_stats.ast_rx_post_crc_err++;
3543218689Sadrian		if (rs->rs_flags & HAL_RX_DECRYPT_BUSY)
3544218689Sadrian			sc->sc_stats.ast_rx_decrypt_busy_err++;
3545218689Sadrian		if (rs->rs_flags & HAL_RX_HI_RX_CHAIN)
3546218689Sadrian			sc->sc_stats.ast_rx_hi_rx_chain++;
3547218689Sadrian
3548170530Ssam		if (rs->rs_status != 0) {
3549165185Ssam			if (rs->rs_status & HAL_RXERR_CRC)
3550116743Ssam				sc->sc_stats.ast_rx_crcerr++;
3551165185Ssam			if (rs->rs_status & HAL_RXERR_FIFO)
3552116743Ssam				sc->sc_stats.ast_rx_fifoerr++;
3553165185Ssam			if (rs->rs_status & HAL_RXERR_PHY) {
3554116743Ssam				sc->sc_stats.ast_rx_phyerr++;
3555222585Sadrian				/* Process DFS radar events */
3556222707Sadrian				if ((rs->rs_phyerr == HAL_PHYERR_RADAR) ||
3557222707Sadrian				    (rs->rs_phyerr == HAL_PHYERR_FALSE_RADAR_EXT)) {
3558222707Sadrian					/* Since we're touching the frame data, sync it */
3559222707Sadrian					bus_dmamap_sync(sc->sc_dmat,
3560222707Sadrian					    bf->bf_dmamap,
3561222707Sadrian					    BUS_DMASYNC_POSTREAD);
3562222707Sadrian					/* Now pass it to the radar processing code */
3563222707Sadrian					ath_dfs_process_phy_err(sc, mtod(m, char *), tsf, rs);
3564222707Sadrian				}
3565222585Sadrian
3566218689Sadrian				/* Be suitably paranoid about receiving phy errors out of the stats array bounds */
3567218689Sadrian				if (rs->rs_phyerr < 64)
3568218689Sadrian					sc->sc_stats.ast_rx_phy[rs->rs_phyerr]++;
3569170530Ssam				goto rx_error;	/* NB: don't count in ierrors */
3570138570Ssam			}
3571165185Ssam			if (rs->rs_status & HAL_RXERR_DECRYPT) {
3572122602Ssam				/*
3573138570Ssam				 * Decrypt error.  If the error occurred
3574138570Ssam				 * because there was no hardware key, then
3575138570Ssam				 * let the frame through so the upper layers
3576138570Ssam				 * can process it.  This is necessary for 5210
3577138570Ssam				 * parts which have no way to setup a ``clear''
3578138570Ssam				 * key cache entry.
3579138570Ssam				 *
3580138570Ssam				 * XXX do key cache faulting
3581122602Ssam				 */
3582165185Ssam				if (rs->rs_keyix == HAL_RXKEYIX_INVALID)
3583138570Ssam					goto rx_accept;
3584138570Ssam				sc->sc_stats.ast_rx_badcrypt++;
3585116743Ssam			}
3586165185Ssam			if (rs->rs_status & HAL_RXERR_MIC) {
3587138570Ssam				sc->sc_stats.ast_rx_badmic++;
3588138570Ssam				/*
3589138570Ssam				 * Do minimal work required to hand off
3590192468Ssam				 * the 802.11 header for notification.
3591138570Ssam				 */
3592138570Ssam				/* XXX frag's and qos frames */
3593165185Ssam				len = rs->rs_datalen;
3594138570Ssam				if (len >= sizeof (struct ieee80211_frame)) {
3595138570Ssam					bus_dmamap_sync(sc->sc_dmat,
3596138570Ssam					    bf->bf_dmamap,
3597138570Ssam					    BUS_DMASYNC_POSTREAD);
3598204100Sdeischen					ath_handle_micerror(ic,
3599138570Ssam					    mtod(m, struct ieee80211_frame *),
3600139499Ssam					    sc->sc_splitmic ?
3601178354Ssam						rs->rs_keyix-32 : rs->rs_keyix);
3602138570Ssam				}
3603138570Ssam			}
3604138570Ssam			ifp->if_ierrors++;
3605170530Ssamrx_error:
3606138570Ssam			/*
3607170530Ssam			 * Cleanup any pending partial frame.
3608170530Ssam			 */
3609170530Ssam			if (sc->sc_rxpending != NULL) {
3610170530Ssam				m_freem(sc->sc_rxpending);
3611170530Ssam				sc->sc_rxpending = NULL;
3612170530Ssam			}
3613170530Ssam			/*
3614154140Ssam			 * When a tap is present pass error frames
3615154140Ssam			 * that have been requested.  By default we
3616154140Ssam			 * pass decrypt+mic errors but others may be
3617154140Ssam			 * interesting (e.g. crc).
3618138570Ssam			 */
3619192468Ssam			if (ieee80211_radiotap_active(ic) &&
3620165185Ssam			    (rs->rs_status & sc->sc_monpass)) {
3621154140Ssam				bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
3622154140Ssam				    BUS_DMASYNC_POSTREAD);
3623154140Ssam				/* NB: bpf needs the mbuf length setup */
3624165185Ssam				len = rs->rs_datalen;
3625154140Ssam				m->m_pkthdr.len = m->m_len = len;
3626192468Ssam				ath_rx_tap(ifp, m, rs, tsf, nf);
3627192468Ssam				ieee80211_radiotap_rx_all(ic, m);
3628154140Ssam			}
3629154140Ssam			/* XXX pass MIC errors up for s/w reclaculation */
3630154140Ssam			goto rx_next;
3631116743Ssam		}
3632138570Ssamrx_accept:
3633138570Ssam		/*
3634138570Ssam		 * Sync and unmap the frame.  At this point we're
3635138570Ssam		 * committed to passing the mbuf somewhere so clear
3636155730Ssam		 * bf_m; this means a new mbuf must be allocated
3637138570Ssam		 * when the rx descriptor is setup again to receive
3638138570Ssam		 * another frame.
3639138570Ssam		 */
3640138570Ssam		bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
3641116743Ssam		    BUS_DMASYNC_POSTREAD);
3642116743Ssam		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
3643116743Ssam		bf->bf_m = NULL;
3644138570Ssam
3645165185Ssam		len = rs->rs_datalen;
3646170530Ssam		m->m_len = len;
3647119783Ssam
3648170530Ssam		if (rs->rs_more) {
3649170530Ssam			/*
3650170530Ssam			 * Frame spans multiple descriptors; save
3651170530Ssam			 * it for the next completed descriptor, it
3652170530Ssam			 * will be used to construct a jumbogram.
3653170530Ssam			 */
3654170530Ssam			if (sc->sc_rxpending != NULL) {
3655170530Ssam				/* NB: max frame size is currently 2 clusters */
3656170530Ssam				sc->sc_stats.ast_rx_toobig++;
3657170530Ssam				m_freem(sc->sc_rxpending);
3658170530Ssam			}
3659170530Ssam			m->m_pkthdr.rcvif = ifp;
3660170530Ssam			m->m_pkthdr.len = len;
3661170530Ssam			sc->sc_rxpending = m;
3662170530Ssam			goto rx_next;
3663170530Ssam		} else if (sc->sc_rxpending != NULL) {
3664170530Ssam			/*
3665170530Ssam			 * This is the second part of a jumbogram,
3666170530Ssam			 * chain it to the first mbuf, adjust the
3667170530Ssam			 * frame length, and clear the rxpending state.
3668170530Ssam			 */
3669170530Ssam			sc->sc_rxpending->m_next = m;
3670170530Ssam			sc->sc_rxpending->m_pkthdr.len += len;
3671170530Ssam			m = sc->sc_rxpending;
3672170530Ssam			sc->sc_rxpending = NULL;
3673170530Ssam		} else {
3674170530Ssam			/*
3675170530Ssam			 * Normal single-descriptor receive; setup
3676170530Ssam			 * the rcvif and packet length.
3677170530Ssam			 */
3678170530Ssam			m->m_pkthdr.rcvif = ifp;
3679170530Ssam			m->m_pkthdr.len = len;
3680170530Ssam		}
3681170530Ssam
3682178354Ssam		ifp->if_ipackets++;
3683165185Ssam		sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
3684138570Ssam
3685192468Ssam		/*
3686192468Ssam		 * Populate the rx status block.  When there are bpf
3687192468Ssam		 * listeners we do the additional work to provide
3688192468Ssam		 * complete status.  Otherwise we fill in only the
3689192468Ssam		 * material required by ieee80211_input.  Note that
3690192468Ssam		 * noise setting is filled in above.
3691192468Ssam		 */
3692192468Ssam		if (ieee80211_radiotap_active(ic))
3693192468Ssam			ath_rx_tap(ifp, m, rs, tsf, nf);
3694119150Ssam
3695138570Ssam		/*
3696138570Ssam		 * From this point on we assume the frame is at least
3697138570Ssam		 * as large as ieee80211_frame_min; verify that.
3698138570Ssam		 */
3699138570Ssam		if (len < IEEE80211_MIN_LEN) {
3700192468Ssam			if (!ieee80211_radiotap_active(ic)) {
3701192468Ssam				DPRINTF(sc, ATH_DEBUG_RECV,
3702192468Ssam				    "%s: short packet %d\n", __func__, len);
3703192468Ssam				sc->sc_stats.ast_rx_tooshort++;
3704192468Ssam			} else {
3705192468Ssam				/* NB: in particular this captures ack's */
3706192468Ssam				ieee80211_radiotap_rx_all(ic, m);
3707192468Ssam			}
3708138570Ssam			m_freem(m);
3709138570Ssam			goto rx_next;
3710116743Ssam		}
3711119150Ssam
3712138570Ssam		if (IFF_DUMPPKTS(sc, ATH_DEBUG_RECV)) {
3713184368Ssam			const HAL_RATE_TABLE *rt = sc->sc_currates;
3714184368Ssam			uint8_t rix = rt->rateCodeToIndex[rs->rs_rate];
3715184368Ssam
3716170530Ssam			ieee80211_dump_pkt(ic, mtod(m, caddr_t), len,
3717184368Ssam			    sc->sc_hwmap[rix].ieeerate, rs->rs_rssi);
3718138570Ssam		}
3719138570Ssam
3720138570Ssam		m_adj(m, -IEEE80211_CRC_LEN);
3721138570Ssam
3722119150Ssam		/*
3723138570Ssam		 * Locate the node for sender, track state, and then
3724138570Ssam		 * pass the (referenced) node up to the 802.11 layer
3725148863Ssam		 * for its use.
3726119150Ssam		 */
3727148863Ssam		ni = ieee80211_find_rxnode_withkey(ic,
3728148863Ssam			mtod(m, const struct ieee80211_frame_min *),
3729165185Ssam			rs->rs_keyix == HAL_RXKEYIX_INVALID ?
3730165185Ssam				IEEE80211_KEYIX_NONE : rs->rs_keyix);
3731209156Sbschmidt		sc->sc_lastrs = rs;
3732218379Sadrian
3733218379Sadrian		if (rs->rs_isaggr)
3734218379Sadrian			sc->sc_stats.ast_rx_agg++;
3735218379Sadrian
3736178354Ssam		if (ni != NULL) {
3737178354Ssam			/*
3738221210Sadrian 			 * Only punt packets for ampdu reorder processing for
3739221210Sadrian			 * 11n nodes; net80211 enforces that M_AMPDU is only
3740221210Sadrian			 * set for 11n nodes.
3741218453Sadrian 			 */
3742218453Sadrian			if (ni->ni_flags & IEEE80211_NODE_HT)
3743218453Sadrian				m->m_flags |= M_AMPDU;
3744218453Sadrian
3745218453Sadrian			/*
3746178354Ssam			 * Sending station is known, dispatch directly.
3747178354Ssam			 */
3748192468Ssam			type = ieee80211_input(ni, m, rs->rs_rssi, nf);
3749178354Ssam			ieee80211_free_node(ni);
3750178354Ssam			/*
3751178354Ssam			 * Arrange to update the last rx timestamp only for
3752178354Ssam			 * frames from our ap when operating in station mode.
3753178354Ssam			 * This assumes the rx key is always setup when
3754178354Ssam			 * associated.
3755178354Ssam			 */
3756178354Ssam			if (ic->ic_opmode == IEEE80211_M_STA &&
3757178354Ssam			    rs->rs_keyix != HAL_RXKEYIX_INVALID)
3758178354Ssam				ngood++;
3759178354Ssam		} else {
3760192468Ssam			type = ieee80211_input_all(ic, m, rs->rs_rssi, nf);
3761178354Ssam		}
3762148863Ssam		/*
3763148863Ssam		 * Track rx rssi and do any rx antenna management.
3764148863Ssam		 */
3765165185Ssam		ATH_RSSI_LPF(sc->sc_halstats.ns_avgrssi, rs->rs_rssi);
3766138570Ssam		if (sc->sc_diversity) {
3767138570Ssam			/*
3768138570Ssam			 * When using fast diversity, change the default rx
3769138570Ssam			 * antenna if diversity chooses the other antenna 3
3770138570Ssam			 * times in a row.
3771138570Ssam			 */
3772165185Ssam			if (sc->sc_defant != rs->rs_antenna) {
3773138570Ssam				if (++sc->sc_rxotherant >= 3)
3774165185Ssam					ath_setdefantenna(sc, rs->rs_antenna);
3775138570Ssam			} else
3776138570Ssam				sc->sc_rxotherant = 0;
3777138570Ssam		}
3778220601Sadrian
3779220601Sadrian		/* Newer school diversity - kite specific for now */
3780220601Sadrian		/* XXX perhaps migrate the normal diversity code to this? */
3781220601Sadrian		if ((ah)->ah_rxAntCombDiversity)
3782220601Sadrian			(*(ah)->ah_rxAntCombDiversity)(ah, rs, ticks, hz);
3783220601Sadrian
3784140432Ssam		if (sc->sc_softled) {
3785140432Ssam			/*
3786140432Ssam			 * Blink for any data frame.  Otherwise do a
3787140432Ssam			 * heartbeat-style blink when idle.  The latter
3788140432Ssam			 * is mainly for station mode where we depend on
3789140432Ssam			 * periodic beacon frames to trigger the poll event.
3790140432Ssam			 */
3791144617Ssam			if (type == IEEE80211_FC0_TYPE_DATA) {
3792184368Ssam				const HAL_RATE_TABLE *rt = sc->sc_currates;
3793204100Sdeischen				ath_led_event(sc,
3794184368Ssam				    rt->rateCodeToIndex[rs->rs_rate]);
3795140432Ssam			} else if (ticks - sc->sc_ledevent >= sc->sc_ledidle)
3796184368Ssam				ath_led_event(sc, 0);
3797140432Ssam		}
3798138570Ssamrx_next:
3799138570Ssam		STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
3800116743Ssam	} while (ath_rxbuf_init(sc, bf) == 0);
3801116743Ssam
3802138570Ssam	/* rx signal state monitoring */
3803187831Ssam	ath_hal_rxmonitor(ah, &sc->sc_halstats, sc->sc_curchan);
3804155492Ssam	if (ngood)
3805155492Ssam		sc->sc_lastrx = tsf;
3806133240Ssam
3807222585Sadrian	/* Queue DFS tasklet if needed */
3808222585Sadrian	if (ath_dfs_tasklet_needed(sc, sc->sc_curchan))
3809222585Sadrian		taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask);
3810222585Sadrian
3811224588Sadrian	/*
3812224588Sadrian	 * Now that all the RX frames were handled that
3813224588Sadrian	 * need to be handled, kick the PCU if there's
3814224588Sadrian	 * been an RXEOL condition.
3815224588Sadrian	 */
3816224588Sadrian	if (sc->sc_kickpcu) {
3817224588Sadrian		sc->sc_kickpcu = 0;
3818224588Sadrian		ath_stoprecv(sc);
3819224588Sadrian		sc->sc_imask |= (HAL_INT_RXEOL | HAL_INT_RXORN);
3820224588Sadrian		if (ath_startrecv(sc) != 0) {
3821224588Sadrian			if_printf(ifp,
3822224588Sadrian			    "%s: couldn't restart RX after RXEOL; resetting\n",
3823224588Sadrian			    __func__);
3824224588Sadrian			ath_reset(ifp);
3825224588Sadrian			return;
3826224588Sadrian		}
3827224588Sadrian		ath_hal_intrset(ah, sc->sc_imask);
3828224588Sadrian	}
3829224588Sadrian
3830190579Ssam	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
3831190579Ssam#ifdef IEEE80211_SUPPORT_SUPERG
3832191753Ssam		ieee80211_ff_age_all(ic, 100);
3833190579Ssam#endif
3834190579Ssam		if (!IFQ_IS_EMPTY(&ifp->if_snd))
3835190579Ssam			ath_start(ifp);
3836190579Ssam	}
3837123044Ssam#undef PA2DESC
3838116743Ssam}
3839116743Ssam
3840159938Ssamstatic void
3841159938Ssamath_txq_init(struct ath_softc *sc, struct ath_txq *txq, int qnum)
3842159938Ssam{
3843159938Ssam	txq->axq_qnum = qnum;
3844190579Ssam	txq->axq_ac = 0;
3845159938Ssam	txq->axq_depth = 0;
3846159938Ssam	txq->axq_intrcnt = 0;
3847159938Ssam	txq->axq_link = NULL;
3848159938Ssam	STAILQ_INIT(&txq->axq_q);
3849159938Ssam	ATH_TXQ_LOCK_INIT(sc, txq);
3850159938Ssam}
3851159938Ssam
3852116743Ssam/*
3853138570Ssam * Setup a h/w transmit queue.
3854116743Ssam */
3855138570Ssamstatic struct ath_txq *
3856138570Ssamath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
3857138570Ssam{
3858138570Ssam#define	N(a)	(sizeof(a)/sizeof(a[0]))
3859138570Ssam	struct ath_hal *ah = sc->sc_ah;
3860138570Ssam	HAL_TXQ_INFO qi;
3861138570Ssam	int qnum;
3862116743Ssam
3863138570Ssam	memset(&qi, 0, sizeof(qi));
3864138570Ssam	qi.tqi_subtype = subtype;
3865138570Ssam	qi.tqi_aifs = HAL_TXQ_USEDEFAULT;
3866138570Ssam	qi.tqi_cwmin = HAL_TXQ_USEDEFAULT;
3867138570Ssam	qi.tqi_cwmax = HAL_TXQ_USEDEFAULT;
3868138570Ssam	/*
3869138570Ssam	 * Enable interrupts only for EOL and DESC conditions.
3870138570Ssam	 * We mark tx descriptors to receive a DESC interrupt
3871138570Ssam	 * when a tx queue gets deep; otherwise waiting for the
3872138570Ssam	 * EOL to reap descriptors.  Note that this is done to
3873138570Ssam	 * reduce interrupt load and this only defers reaping
3874138570Ssam	 * descriptors, never transmitting frames.  Aside from
3875138570Ssam	 * reducing interrupts this also permits more concurrency.
3876138570Ssam	 * The only potential downside is if the tx queue backs
3877138570Ssam	 * up in which case the top half of the kernel may backup
3878138570Ssam	 * due to a lack of tx descriptors.
3879138570Ssam	 */
3880155515Ssam	qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_TXDESCINT_ENABLE;
3881138570Ssam	qnum = ath_hal_setuptxqueue(ah, qtype, &qi);
3882138570Ssam	if (qnum == -1) {
3883138570Ssam		/*
3884147057Ssam		 * NB: don't print a message, this happens
3885139501Ssam		 * normally on parts with too few tx queues
3886138570Ssam		 */
3887138570Ssam		return NULL;
3888138570Ssam	}
3889138570Ssam	if (qnum >= N(sc->sc_txq)) {
3890138878Speter		device_printf(sc->sc_dev,
3891138878Speter			"hal qnum %u out of range, max %zu!\n",
3892138570Ssam			qnum, N(sc->sc_txq));
3893138570Ssam		ath_hal_releasetxqueue(ah, qnum);
3894138570Ssam		return NULL;
3895138570Ssam	}
3896138570Ssam	if (!ATH_TXQ_SETUP(sc, qnum)) {
3897159938Ssam		ath_txq_init(sc, &sc->sc_txq[qnum], qnum);
3898138570Ssam		sc->sc_txqsetup |= 1<<qnum;
3899138570Ssam	}
3900138570Ssam	return &sc->sc_txq[qnum];
3901138570Ssam#undef N
3902138570Ssam}
3903138570Ssam
3904138570Ssam/*
3905138570Ssam * Setup a hardware data transmit queue for the specified
3906138570Ssam * access control.  The hal may not support all requested
3907138570Ssam * queues in which case it will return a reference to a
3908138570Ssam * previously setup queue.  We record the mapping from ac's
3909138570Ssam * to h/w queues for use by ath_tx_start and also track
3910138570Ssam * the set of h/w queues being used to optimize work in the
3911138570Ssam * transmit interrupt handler and related routines.
3912138570Ssam */
3913116743Ssamstatic int
3914138570Ssamath_tx_setup(struct ath_softc *sc, int ac, int haltype)
3915138570Ssam{
3916138570Ssam#define	N(a)	(sizeof(a)/sizeof(a[0]))
3917138570Ssam	struct ath_txq *txq;
3918138570Ssam
3919138570Ssam	if (ac >= N(sc->sc_ac2q)) {
3920138878Speter		device_printf(sc->sc_dev, "AC %u out of range, max %zu!\n",
3921138570Ssam			ac, N(sc->sc_ac2q));
3922138570Ssam		return 0;
3923138570Ssam	}
3924138570Ssam	txq = ath_txq_setup(sc, HAL_TX_QUEUE_DATA, haltype);
3925138570Ssam	if (txq != NULL) {
3926190579Ssam		txq->axq_ac = ac;
3927138570Ssam		sc->sc_ac2q[ac] = txq;
3928138570Ssam		return 1;
3929138570Ssam	} else
3930138570Ssam		return 0;
3931138570Ssam#undef N
3932138570Ssam}
3933138570Ssam
3934138570Ssam/*
3935138570Ssam * Update WME parameters for a transmit queue.
3936138570Ssam */
3937138570Ssamstatic int
3938138570Ssamath_txq_update(struct ath_softc *sc, int ac)
3939138570Ssam{
3940138570Ssam#define	ATH_EXPONENT_TO_VALUE(v)	((1<<v)-1)
3941138570Ssam#define	ATH_TXOP_TO_US(v)		(v<<5)
3942178354Ssam	struct ifnet *ifp = sc->sc_ifp;
3943178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
3944138570Ssam	struct ath_txq *txq = sc->sc_ac2q[ac];
3945138570Ssam	struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
3946138570Ssam	struct ath_hal *ah = sc->sc_ah;
3947138570Ssam	HAL_TXQ_INFO qi;
3948138570Ssam
3949138570Ssam	ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi);
3950190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
3951186904Ssam	if (sc->sc_tdma) {
3952186904Ssam		/*
3953186904Ssam		 * AIFS is zero so there's no pre-transmit wait.  The
3954186904Ssam		 * burst time defines the slot duration and is configured
3955193350Ssam		 * through net80211.  The QCU is setup to not do post-xmit
3956186904Ssam		 * back off, lockout all lower-priority QCU's, and fire
3957186904Ssam		 * off the DMA beacon alert timer which is setup based
3958186904Ssam		 * on the slot configuration.
3959186904Ssam		 */
3960186904Ssam		qi.tqi_qflags = HAL_TXQ_TXOKINT_ENABLE
3961186904Ssam			      | HAL_TXQ_TXERRINT_ENABLE
3962186904Ssam			      | HAL_TXQ_TXURNINT_ENABLE
3963186904Ssam			      | HAL_TXQ_TXEOLINT_ENABLE
3964186904Ssam			      | HAL_TXQ_DBA_GATED
3965186904Ssam			      | HAL_TXQ_BACKOFF_DISABLE
3966186904Ssam			      | HAL_TXQ_ARB_LOCKOUT_GLOBAL
3967186904Ssam			      ;
3968186904Ssam		qi.tqi_aifs = 0;
3969186904Ssam		/* XXX +dbaprep? */
3970186904Ssam		qi.tqi_readyTime = sc->sc_tdmaslotlen;
3971186904Ssam		qi.tqi_burstTime = qi.tqi_readyTime;
3972186904Ssam	} else {
3973186904Ssam#endif
3974186904Ssam		qi.tqi_qflags = HAL_TXQ_TXOKINT_ENABLE
3975186904Ssam			      | HAL_TXQ_TXERRINT_ENABLE
3976186904Ssam			      | HAL_TXQ_TXDESCINT_ENABLE
3977186904Ssam			      | HAL_TXQ_TXURNINT_ENABLE
3978186904Ssam			      ;
3979186904Ssam		qi.tqi_aifs = wmep->wmep_aifsn;
3980186904Ssam		qi.tqi_cwmin = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmin);
3981186904Ssam		qi.tqi_cwmax = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmax);
3982186904Ssam		qi.tqi_readyTime = 0;
3983186904Ssam		qi.tqi_burstTime = ATH_TXOP_TO_US(wmep->wmep_txopLimit);
3984190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
3985186904Ssam	}
3986186904Ssam#endif
3987138570Ssam
3988186904Ssam	DPRINTF(sc, ATH_DEBUG_RESET,
3989186904Ssam	    "%s: Q%u qflags 0x%x aifs %u cwmin %u cwmax %u burstTime %u\n",
3990186904Ssam	    __func__, txq->axq_qnum, qi.tqi_qflags,
3991186904Ssam	    qi.tqi_aifs, qi.tqi_cwmin, qi.tqi_cwmax, qi.tqi_burstTime);
3992186904Ssam
3993138570Ssam	if (!ath_hal_settxqueueprops(ah, txq->axq_qnum, &qi)) {
3994178354Ssam		if_printf(ifp, "unable to update hardware queue "
3995138570Ssam			"parameters for %s traffic!\n",
3996138570Ssam			ieee80211_wme_acnames[ac]);
3997138570Ssam		return 0;
3998138570Ssam	} else {
3999138570Ssam		ath_hal_resettxqueue(ah, txq->axq_qnum); /* push to h/w */
4000138570Ssam		return 1;
4001138570Ssam	}
4002138570Ssam#undef ATH_TXOP_TO_US
4003138570Ssam#undef ATH_EXPONENT_TO_VALUE
4004138570Ssam}
4005138570Ssam
4006138570Ssam/*
4007138570Ssam * Callback from the 802.11 layer to update WME parameters.
4008138570Ssam */
4009147057Ssamstatic int
4010138570Ssamath_wme_update(struct ieee80211com *ic)
4011138570Ssam{
4012138570Ssam	struct ath_softc *sc = ic->ic_ifp->if_softc;
4013138570Ssam
4014138570Ssam	return !ath_txq_update(sc, WME_AC_BE) ||
4015138570Ssam	    !ath_txq_update(sc, WME_AC_BK) ||
4016138570Ssam	    !ath_txq_update(sc, WME_AC_VI) ||
4017138570Ssam	    !ath_txq_update(sc, WME_AC_VO) ? EIO : 0;
4018138570Ssam}
4019138570Ssam
4020138570Ssam/*
4021138570Ssam * Reclaim resources for a setup queue.
4022138570Ssam */
4023138570Ssamstatic void
4024138570Ssamath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
4025138570Ssam{
4026138570Ssam
4027138570Ssam	ath_hal_releasetxqueue(sc->sc_ah, txq->axq_qnum);
4028138570Ssam	ATH_TXQ_LOCK_DESTROY(txq);
4029138570Ssam	sc->sc_txqsetup &= ~(1<<txq->axq_qnum);
4030138570Ssam}
4031138570Ssam
4032138570Ssam/*
4033138570Ssam * Reclaim all tx queue resources.
4034138570Ssam */
4035138570Ssamstatic void
4036138570Ssamath_tx_cleanup(struct ath_softc *sc)
4037138570Ssam{
4038138570Ssam	int i;
4039138570Ssam
4040138570Ssam	ATH_TXBUF_LOCK_DESTROY(sc);
4041138570Ssam	for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
4042138570Ssam		if (ATH_TXQ_SETUP(sc, i))
4043138570Ssam			ath_tx_cleanupq(sc, &sc->sc_txq[i]);
4044138570Ssam}
4045138570Ssam
4046144305Ssam/*
4047191866Ssam * Return h/w rate index for an IEEE rate (w/o basic rate bit)
4048191866Ssam * using the current rates in sc_rixmap.
4049155483Ssam */
4050218065Sadrianint
4051191866Ssamath_tx_findrix(const struct ath_softc *sc, uint8_t rate)
4052155483Ssam{
4053191866Ssam	int rix = sc->sc_rixmap[rate];
4054191866Ssam	/* NB: return lowest rix for invalid rate */
4055191866Ssam	return (rix == 0xff ? 0 : rix);
4056155483Ssam}
4057155483Ssam
4058170530Ssam/*
4059138570Ssam * Process completed xmit descriptors from the specified queue.
4060138570Ssam */
4061155492Ssamstatic int
4062138570Ssamath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
4063116743Ssam{
4064116743Ssam	struct ath_hal *ah = sc->sc_ah;
4065178354Ssam	struct ifnet *ifp = sc->sc_ifp;
4066178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
4067186904Ssam	struct ath_buf *bf, *last;
4068144346Ssam	struct ath_desc *ds, *ds0;
4069165185Ssam	struct ath_tx_status *ts;
4070116743Ssam	struct ieee80211_node *ni;
4071116743Ssam	struct ath_node *an;
4072155492Ssam	int sr, lr, pri, nacked;
4073116743Ssam	HAL_STATUS status;
4074116743Ssam
4075138570Ssam	DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: tx queue %u head %p link %p\n",
4076138570Ssam		__func__, txq->axq_qnum,
4077138570Ssam		(caddr_t)(uintptr_t) ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum),
4078138570Ssam		txq->axq_link);
4079155492Ssam	nacked = 0;
4080116743Ssam	for (;;) {
4081138570Ssam		ATH_TXQ_LOCK(txq);
4082138570Ssam		txq->axq_intrcnt = 0;	/* reset periodic desc intr count */
4083138570Ssam		bf = STAILQ_FIRST(&txq->axq_q);
4084116743Ssam		if (bf == NULL) {
4085138570Ssam			ATH_TXQ_UNLOCK(txq);
4086116743Ssam			break;
4087116743Ssam		}
4088144346Ssam		ds0 = &bf->bf_desc[0];
4089116743Ssam		ds = &bf->bf_desc[bf->bf_nseg - 1];
4090165185Ssam		ts = &bf->bf_status.ds_txstat;
4091165185Ssam		status = ath_hal_txprocdesc(ah, ds, ts);
4092157438Ssam#ifdef ATH_DEBUG
4093138570Ssam		if (sc->sc_debug & ATH_DEBUG_XMIT_DESC)
4094185243Ssam			ath_printtxbuf(sc, bf, txq->axq_qnum, 0,
4095185243Ssam			    status == HAL_OK);
4096116743Ssam#endif
4097116743Ssam		if (status == HAL_EINPROGRESS) {
4098138570Ssam			ATH_TXQ_UNLOCK(txq);
4099116743Ssam			break;
4100116743Ssam		}
4101138570Ssam		ATH_TXQ_REMOVE_HEAD(txq, bf_list);
4102190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
4103186904Ssam		if (txq->axq_depth > 0) {
4104186904Ssam			/*
4105186904Ssam			 * More frames follow.  Mark the buffer busy
4106186904Ssam			 * so it's not re-used while the hardware may
4107186904Ssam			 * still re-read the link field in the descriptor.
4108186904Ssam			 */
4109186904Ssam			bf->bf_flags |= ATH_BUF_BUSY;
4110186904Ssam		} else
4111186904Ssam#else
4112156073Ssam		if (txq->axq_depth == 0)
4113186904Ssam#endif
4114155729Ssam			txq->axq_link = NULL;
4115138570Ssam		ATH_TXQ_UNLOCK(txq);
4116116743Ssam
4117116743Ssam		ni = bf->bf_node;
4118116743Ssam		if (ni != NULL) {
4119138570Ssam			an = ATH_NODE(ni);
4120165185Ssam			if (ts->ts_status == 0) {
4121165185Ssam				u_int8_t txant = ts->ts_antenna;
4122138570Ssam				sc->sc_stats.ast_ant_tx[txant]++;
4123138570Ssam				sc->sc_ant_tx[txant]++;
4124194135Ssam				if (ts->ts_finaltsi != 0)
4125138570Ssam					sc->sc_stats.ast_tx_altrate++;
4126138570Ssam				pri = M_WME_GETAC(bf->bf_m);
4127138570Ssam				if (pri >= WME_AC_VO)
4128138570Ssam					ic->ic_wme.wme_hipri_traffic++;
4129184357Ssam				if ((bf->bf_txflags & HAL_TXDESC_NOACK) == 0)
4130184357Ssam					ni->ni_inact = ni->ni_inact_reload;
4131116743Ssam			} else {
4132165185Ssam				if (ts->ts_status & HAL_TXERR_XRETRY)
4133116743Ssam					sc->sc_stats.ast_tx_xretries++;
4134165185Ssam				if (ts->ts_status & HAL_TXERR_FIFO)
4135116743Ssam					sc->sc_stats.ast_tx_fifoerr++;
4136165185Ssam				if (ts->ts_status & HAL_TXERR_FILT)
4137116743Ssam					sc->sc_stats.ast_tx_filtered++;
4138221965Sadrian				if (ts->ts_status & HAL_TXERR_XTXOP)
4139221965Sadrian					sc->sc_stats.ast_tx_xtxop++;
4140221965Sadrian				if (ts->ts_status & HAL_TXERR_TIMER_EXPIRED)
4141221965Sadrian					sc->sc_stats.ast_tx_timerexpired++;
4142221965Sadrian
4143221965Sadrian				/* XXX HAL_TX_DATA_UNDERRUN */
4144221965Sadrian				/* XXX HAL_TX_DELIM_UNDERRUN */
4145221965Sadrian
4146170530Ssam				if (bf->bf_m->m_flags & M_FF)
4147170530Ssam					sc->sc_stats.ast_ff_txerr++;
4148116743Ssam			}
4149221965Sadrian			/* XXX when is this valid? */
4150221965Sadrian			if (ts->ts_status & HAL_TX_DESC_CFG_ERR)
4151221965Sadrian				sc->sc_stats.ast_tx_desccfgerr++;
4152221965Sadrian
4153165185Ssam			sr = ts->ts_shortretry;
4154165185Ssam			lr = ts->ts_longretry;
4155116743Ssam			sc->sc_stats.ast_tx_shortretry += sr;
4156116743Ssam			sc->sc_stats.ast_tx_longretry += lr;
4157119150Ssam			/*
4158138570Ssam			 * Hand the descriptor to the rate control algorithm.
4159138570Ssam			 */
4160165185Ssam			if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
4161184351Ssam			    (bf->bf_txflags & HAL_TXDESC_NOACK) == 0) {
4162155492Ssam				/*
4163184358Ssam				 * If frame was ack'd update statistics,
4164184358Ssam				 * including the last rx time used to
4165184358Ssam				 * workaround phantom bmiss interrupts.
4166155492Ssam				 */
4167184358Ssam				if (ts->ts_status == 0) {
4168155492Ssam					nacked++;
4169184358Ssam					sc->sc_stats.ast_tx_rssi = ts->ts_rssi;
4170184358Ssam					ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi,
4171184358Ssam						ts->ts_rssi);
4172184358Ssam				}
4173165185Ssam				ath_rate_tx_complete(sc, an, bf);
4174155492Ssam			}
4175138570Ssam			/*
4176170530Ssam			 * Do any tx complete callback.  Note this must
4177170530Ssam			 * be done before releasing the node reference.
4178170530Ssam			 */
4179170530Ssam			if (bf->bf_m->m_flags & M_TXCB)
4180170530Ssam				ieee80211_process_callback(ni, bf->bf_m,
4181184359Ssam				    (bf->bf_txflags & HAL_TXDESC_NOACK) == 0 ?
4182184359Ssam				        ts->ts_status : HAL_TXERR_XRETRY);
4183138570Ssam			ieee80211_free_node(ni);
4184116743Ssam		}
4185116743Ssam		bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
4186116743Ssam		    BUS_DMASYNC_POSTWRITE);
4187116743Ssam		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
4188170530Ssam
4189116743Ssam		m_freem(bf->bf_m);
4190116743Ssam		bf->bf_m = NULL;
4191116743Ssam		bf->bf_node = NULL;
4192116743Ssam
4193121100Ssam		ATH_TXBUF_LOCK(sc);
4194186904Ssam		last = STAILQ_LAST(&sc->sc_txbuf, ath_buf, bf_list);
4195186904Ssam		if (last != NULL)
4196186904Ssam			last->bf_flags &= ~ATH_BUF_BUSY;
4197138570Ssam		STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
4198121100Ssam		ATH_TXBUF_UNLOCK(sc);
4199116743Ssam	}
4200190579Ssam#ifdef IEEE80211_SUPPORT_SUPERG
4201170530Ssam	/*
4202170530Ssam	 * Flush fast-frame staging queue when traffic slows.
4203170530Ssam	 */
4204170530Ssam	if (txq->axq_depth <= 1)
4205191753Ssam		ieee80211_ff_flush(ic, txq->axq_ac);
4206190579Ssam#endif
4207155492Ssam	return nacked;
4208138570Ssam}
4209138570Ssam
4210155492Ssamstatic __inline int
4211155492Ssamtxqactive(struct ath_hal *ah, int qnum)
4212155492Ssam{
4213155731Ssam	u_int32_t txqs = 1<<qnum;
4214155731Ssam	ath_hal_gettxintrtxqs(ah, &txqs);
4215155733Ssam	return (txqs & (1<<qnum));
4216155492Ssam}
4217155492Ssam
4218138570Ssam/*
4219138570Ssam * Deferred processing of transmit interrupt; special-cased
4220138570Ssam * for a single hardware transmit queue (e.g. 5210 and 5211).
4221138570Ssam */
4222138570Ssamstatic void
4223138570Ssamath_tx_proc_q0(void *arg, int npending)
4224138570Ssam{
4225138570Ssam	struct ath_softc *sc = arg;
4226147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
4227138570Ssam
4228155492Ssam	if (txqactive(sc->sc_ah, 0) && ath_tx_processq(sc, &sc->sc_txq[0]))
4229155492Ssam		sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
4230155492Ssam	if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
4231155492Ssam		ath_tx_processq(sc, sc->sc_cabq);
4232148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
4233189605Ssam	sc->sc_wd_timer = 0;
4234116743Ssam
4235140432Ssam	if (sc->sc_softled)
4236184368Ssam		ath_led_event(sc, sc->sc_txrix);
4237140432Ssam
4238116743Ssam	ath_start(ifp);
4239116743Ssam}
4240116743Ssam
4241116743Ssam/*
4242138570Ssam * Deferred processing of transmit interrupt; special-cased
4243138570Ssam * for four hardware queues, 0-3 (e.g. 5212 w/ WME support).
4244116743Ssam */
4245116743Ssamstatic void
4246138570Ssamath_tx_proc_q0123(void *arg, int npending)
4247116743Ssam{
4248138570Ssam	struct ath_softc *sc = arg;
4249147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
4250155492Ssam	int nacked;
4251138570Ssam
4252138570Ssam	/*
4253138570Ssam	 * Process each active queue.
4254138570Ssam	 */
4255155492Ssam	nacked = 0;
4256155492Ssam	if (txqactive(sc->sc_ah, 0))
4257155492Ssam		nacked += ath_tx_processq(sc, &sc->sc_txq[0]);
4258155492Ssam	if (txqactive(sc->sc_ah, 1))
4259155492Ssam		nacked += ath_tx_processq(sc, &sc->sc_txq[1]);
4260155492Ssam	if (txqactive(sc->sc_ah, 2))
4261155492Ssam		nacked += ath_tx_processq(sc, &sc->sc_txq[2]);
4262155492Ssam	if (txqactive(sc->sc_ah, 3))
4263155492Ssam		nacked += ath_tx_processq(sc, &sc->sc_txq[3]);
4264155492Ssam	if (txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))
4265155492Ssam		ath_tx_processq(sc, sc->sc_cabq);
4266155492Ssam	if (nacked)
4267155492Ssam		sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
4268138570Ssam
4269148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
4270189605Ssam	sc->sc_wd_timer = 0;
4271138570Ssam
4272140432Ssam	if (sc->sc_softled)
4273184368Ssam		ath_led_event(sc, sc->sc_txrix);
4274140432Ssam
4275138570Ssam	ath_start(ifp);
4276138570Ssam}
4277138570Ssam
4278138570Ssam/*
4279138570Ssam * Deferred processing of transmit interrupt.
4280138570Ssam */
4281138570Ssamstatic void
4282138570Ssamath_tx_proc(void *arg, int npending)
4283138570Ssam{
4284138570Ssam	struct ath_softc *sc = arg;
4285147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
4286155492Ssam	int i, nacked;
4287138570Ssam
4288138570Ssam	/*
4289138570Ssam	 * Process each active queue.
4290138570Ssam	 */
4291155492Ssam	nacked = 0;
4292138570Ssam	for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
4293155492Ssam		if (ATH_TXQ_SETUP(sc, i) && txqactive(sc->sc_ah, i))
4294155492Ssam			nacked += ath_tx_processq(sc, &sc->sc_txq[i]);
4295155492Ssam	if (nacked)
4296155492Ssam		sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
4297138570Ssam
4298148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
4299189605Ssam	sc->sc_wd_timer = 0;
4300138570Ssam
4301140432Ssam	if (sc->sc_softled)
4302184368Ssam		ath_led_event(sc, sc->sc_txrix);
4303140432Ssam
4304138570Ssam	ath_start(ifp);
4305138570Ssam}
4306138570Ssam
4307138570Ssamstatic void
4308138570Ssamath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
4309138570Ssam{
4310157438Ssam#ifdef ATH_DEBUG
4311116743Ssam	struct ath_hal *ah = sc->sc_ah;
4312155735Ssam#endif
4313124225Ssam	struct ieee80211_node *ni;
4314116743Ssam	struct ath_buf *bf;
4315155734Ssam	u_int ix;
4316116743Ssam
4317138570Ssam	/*
4318138570Ssam	 * NB: this assumes output has been stopped and
4319184360Ssam	 *     we do not need to block ath_tx_proc
4320138570Ssam	 */
4321186904Ssam	ATH_TXBUF_LOCK(sc);
4322186904Ssam	bf = STAILQ_LAST(&sc->sc_txbuf, ath_buf, bf_list);
4323186904Ssam	if (bf != NULL)
4324186904Ssam		bf->bf_flags &= ~ATH_BUF_BUSY;
4325186904Ssam	ATH_TXBUF_UNLOCK(sc);
4326155734Ssam	for (ix = 0;; ix++) {
4327138570Ssam		ATH_TXQ_LOCK(txq);
4328138570Ssam		bf = STAILQ_FIRST(&txq->axq_q);
4329116743Ssam		if (bf == NULL) {
4330156073Ssam			txq->axq_link = NULL;
4331138570Ssam			ATH_TXQ_UNLOCK(txq);
4332116743Ssam			break;
4333116743Ssam		}
4334138570Ssam		ATH_TXQ_REMOVE_HEAD(txq, bf_list);
4335138570Ssam		ATH_TXQ_UNLOCK(txq);
4336157438Ssam#ifdef ATH_DEBUG
4337157798Ssam		if (sc->sc_debug & ATH_DEBUG_RESET) {
4338178354Ssam			struct ieee80211com *ic = sc->sc_ifp->if_l2com;
4339178354Ssam
4340185243Ssam			ath_printtxbuf(sc, bf, txq->axq_qnum, ix,
4341165185Ssam				ath_hal_txprocdesc(ah, bf->bf_desc,
4342165185Ssam				    &bf->bf_status.ds_txstat) == HAL_OK);
4343191021Ssam			ieee80211_dump_pkt(ic, mtod(bf->bf_m, const uint8_t *),
4344191021Ssam			    bf->bf_m->m_len, 0, -1);
4345157798Ssam		}
4346157438Ssam#endif /* ATH_DEBUG */
4347116743Ssam		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
4348124225Ssam		ni = bf->bf_node;
4349116743Ssam		bf->bf_node = NULL;
4350138570Ssam		if (ni != NULL) {
4351124225Ssam			/*
4352171015Ssam			 * Do any callback and reclaim the node reference.
4353124225Ssam			 */
4354171015Ssam			if (bf->bf_m->m_flags & M_TXCB)
4355171015Ssam				ieee80211_process_callback(ni, bf->bf_m, -1);
4356138570Ssam			ieee80211_free_node(ni);
4357124225Ssam		}
4358170530Ssam		m_freem(bf->bf_m);
4359170530Ssam		bf->bf_m = NULL;
4360186904Ssam		bf->bf_flags &= ~ATH_BUF_BUSY;
4361170530Ssam
4362121100Ssam		ATH_TXBUF_LOCK(sc);
4363138570Ssam		STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
4364121100Ssam		ATH_TXBUF_UNLOCK(sc);
4365116743Ssam	}
4366138570Ssam}
4367138570Ssam
4368138570Ssamstatic void
4369138570Ssamath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
4370138570Ssam{
4371138570Ssam	struct ath_hal *ah = sc->sc_ah;
4372138570Ssam
4373138570Ssam	DPRINTF(sc, ATH_DEBUG_RESET, "%s: tx queue [%u] %p, link %p\n",
4374138570Ssam	    __func__, txq->axq_qnum,
4375138878Speter	    (caddr_t)(uintptr_t) ath_hal_gettxbuf(ah, txq->axq_qnum),
4376138878Speter	    txq->axq_link);
4377157798Ssam	(void) ath_hal_stoptxdma(ah, txq->axq_qnum);
4378138570Ssam}
4379138570Ssam
4380138570Ssam/*
4381138570Ssam * Drain the transmit queues and reclaim resources.
4382138570Ssam */
4383138570Ssamstatic void
4384138570Ssamath_draintxq(struct ath_softc *sc)
4385138570Ssam{
4386138570Ssam	struct ath_hal *ah = sc->sc_ah;
4387147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
4388138570Ssam	int i;
4389138570Ssam
4390138570Ssam	/* XXX return value */
4391138570Ssam	if (!sc->sc_invalid) {
4392138570Ssam		/* don't touch the hardware if marked invalid */
4393157798Ssam		DPRINTF(sc, ATH_DEBUG_RESET, "%s: tx queue [%u] %p, link %p\n",
4394157798Ssam		    __func__, sc->sc_bhalq,
4395157798Ssam		    (caddr_t)(uintptr_t) ath_hal_gettxbuf(ah, sc->sc_bhalq),
4396157798Ssam		    NULL);
4397138570Ssam		(void) ath_hal_stoptxdma(ah, sc->sc_bhalq);
4398138570Ssam		for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
4399138570Ssam			if (ATH_TXQ_SETUP(sc, i))
4400138570Ssam				ath_tx_stopdma(sc, &sc->sc_txq[i]);
4401138570Ssam	}
4402138570Ssam	for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
4403138570Ssam		if (ATH_TXQ_SETUP(sc, i))
4404138570Ssam			ath_tx_draintxq(sc, &sc->sc_txq[i]);
4405157798Ssam#ifdef ATH_DEBUG
4406157798Ssam	if (sc->sc_debug & ATH_DEBUG_RESET) {
4407157798Ssam		struct ath_buf *bf = STAILQ_FIRST(&sc->sc_bbuf);
4408157798Ssam		if (bf != NULL && bf->bf_m != NULL) {
4409185243Ssam			ath_printtxbuf(sc, bf, sc->sc_bhalq, 0,
4410165185Ssam				ath_hal_txprocdesc(ah, bf->bf_desc,
4411165185Ssam				    &bf->bf_status.ds_txstat) == HAL_OK);
4412191021Ssam			ieee80211_dump_pkt(ifp->if_l2com,
4413191021Ssam			    mtod(bf->bf_m, const uint8_t *), bf->bf_m->m_len,
4414191021Ssam			    0, -1);
4415157798Ssam		}
4416157798Ssam	}
4417157798Ssam#endif /* ATH_DEBUG */
4418148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
4419189605Ssam	sc->sc_wd_timer = 0;
4420116743Ssam}
4421116743Ssam
4422116743Ssam/*
4423116743Ssam * Disable the receive h/w in preparation for a reset.
4424116743Ssam */
4425116743Ssamstatic void
4426116743Ssamath_stoprecv(struct ath_softc *sc)
4427116743Ssam{
4428123044Ssam#define	PA2DESC(_sc, _pa) \
4429138570Ssam	((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
4430138570Ssam		((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
4431116743Ssam	struct ath_hal *ah = sc->sc_ah;
4432116743Ssam
4433116743Ssam	ath_hal_stoppcurecv(ah);	/* disable PCU */
4434116743Ssam	ath_hal_setrxfilter(ah, 0);	/* clear recv filter */
4435116743Ssam	ath_hal_stopdmarecv(ah);	/* disable DMA engine */
4436138570Ssam	DELAY(3000);			/* 3ms is long enough for 1 frame */
4437157438Ssam#ifdef ATH_DEBUG
4438138570Ssam	if (sc->sc_debug & (ATH_DEBUG_RESET | ATH_DEBUG_FATAL)) {
4439116743Ssam		struct ath_buf *bf;
4440155734Ssam		u_int ix;
4441116743Ssam
4442124220Ssam		printf("%s: rx queue %p, link %p\n", __func__,
4443125510Speter			(caddr_t)(uintptr_t) ath_hal_getrxbuf(ah), sc->sc_rxlink);
4444155734Ssam		ix = 0;
4445138570Ssam		STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
4446123044Ssam			struct ath_desc *ds = bf->bf_desc;
4447165185Ssam			struct ath_rx_status *rs = &bf->bf_status.ds_rxstat;
4448138570Ssam			HAL_STATUS status = ath_hal_rxprocdesc(ah, ds,
4449165185Ssam				bf->bf_daddr, PA2DESC(sc, ds->ds_link), rs);
4450138570Ssam			if (status == HAL_OK || (sc->sc_debug & ATH_DEBUG_FATAL))
4451185243Ssam				ath_printrxbuf(sc, bf, ix, status == HAL_OK);
4452155734Ssam			ix++;
4453116743Ssam		}
4454116743Ssam	}
4455116743Ssam#endif
4456170530Ssam	if (sc->sc_rxpending != NULL) {
4457170530Ssam		m_freem(sc->sc_rxpending);
4458170530Ssam		sc->sc_rxpending = NULL;
4459170530Ssam	}
4460116743Ssam	sc->sc_rxlink = NULL;		/* just in case */
4461123044Ssam#undef PA2DESC
4462116743Ssam}
4463116743Ssam
4464116743Ssam/*
4465116743Ssam * Enable the receive h/w following a reset.
4466116743Ssam */
4467116743Ssamstatic int
4468116743Ssamath_startrecv(struct ath_softc *sc)
4469116743Ssam{
4470116743Ssam	struct ath_hal *ah = sc->sc_ah;
4471116743Ssam	struct ath_buf *bf;
4472116743Ssam
4473116743Ssam	sc->sc_rxlink = NULL;
4474170530Ssam	sc->sc_rxpending = NULL;
4475138570Ssam	STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
4476116743Ssam		int error = ath_rxbuf_init(sc, bf);
4477116743Ssam		if (error != 0) {
4478138570Ssam			DPRINTF(sc, ATH_DEBUG_RECV,
4479138570Ssam				"%s: ath_rxbuf_init failed %d\n",
4480138570Ssam				__func__, error);
4481116743Ssam			return error;
4482116743Ssam		}
4483116743Ssam	}
4484116743Ssam
4485138570Ssam	bf = STAILQ_FIRST(&sc->sc_rxbuf);
4486116743Ssam	ath_hal_putrxbuf(ah, bf->bf_daddr);
4487116743Ssam	ath_hal_rxena(ah);		/* enable recv descriptors */
4488116743Ssam	ath_mode_init(sc);		/* set filters, etc. */
4489116743Ssam	ath_hal_startpcurecv(ah);	/* re-enable PCU/DMA engine */
4490116743Ssam	return 0;
4491116743Ssam}
4492116743Ssam
4493204100Sdeischen/*
4494138570Ssam * Update internal state after a channel change.
4495138570Ssam */
4496138570Ssamstatic void
4497138570Ssamath_chan_change(struct ath_softc *sc, struct ieee80211_channel *chan)
4498138570Ssam{
4499138570Ssam	enum ieee80211_phymode mode;
4500138570Ssam
4501138570Ssam	/*
4502138570Ssam	 * Change channels and update the h/w rate map
4503138570Ssam	 * if we're switching; e.g. 11a to 11b/g.
4504138570Ssam	 */
4505188783Ssam	mode = ieee80211_chan2mode(chan);
4506138570Ssam	if (mode != sc->sc_curmode)
4507138570Ssam		ath_setcurmode(sc, mode);
4508187831Ssam	sc->sc_curchan = chan;
4509138570Ssam}
4510138570Ssam
4511116743Ssam/*
4512116743Ssam * Set/change channels.  If the channel is really being changed,
4513204100Sdeischen * it's done by resetting the chip.  To accomplish this we must
4514116743Ssam * first cleanup any pending DMA, then restart stuff after a la
4515116743Ssam * ath_init.
4516116743Ssam */
4517116743Ssamstatic int
4518116743Ssamath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
4519116743Ssam{
4520178354Ssam	struct ifnet *ifp = sc->sc_ifp;
4521178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
4522116743Ssam	struct ath_hal *ah = sc->sc_ah;
4523116743Ssam
4524187831Ssam	DPRINTF(sc, ATH_DEBUG_RESET, "%s: %u (%u MHz, flags 0x%x)\n",
4525187831Ssam	    __func__, ieee80211_chan2ieee(ic, chan),
4526187831Ssam	    chan->ic_freq, chan->ic_flags);
4527187831Ssam	if (chan != sc->sc_curchan) {
4528116743Ssam		HAL_STATUS status;
4529116743Ssam		/*
4530116743Ssam		 * To switch channels clear any pending DMA operations;
4531116743Ssam		 * wait long enough for the RX fifo to drain, reset the
4532116743Ssam		 * hardware at the new frequency, and then re-enable
4533116743Ssam		 * the relevant bits of the h/w.
4534116743Ssam		 */
4535116743Ssam		ath_hal_intrset(ah, 0);		/* disable interrupts */
4536116743Ssam		ath_draintxq(sc);		/* clear pending tx frames */
4537116743Ssam		ath_stoprecv(sc);		/* turn off frame recv */
4538187831Ssam		if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) {
4539178354Ssam			if_printf(ifp, "%s: unable to reset "
4540202161Sgavin			    "channel %u (%u MHz, flags 0x%x), hal status %u\n",
4541187831Ssam			    __func__, ieee80211_chan2ieee(ic, chan),
4542187831Ssam			    chan->ic_freq, chan->ic_flags, status);
4543116743Ssam			return EIO;
4544116743Ssam		}
4545148362Ssam		sc->sc_diversity = ath_hal_getdiversity(ah);
4546138570Ssam
4547222585Sadrian		/* Let DFS at it in case it's a DFS channel */
4548222585Sadrian		ath_dfs_radar_enable(sc, ic->ic_curchan);
4549222585Sadrian
4550116743Ssam		/*
4551116743Ssam		 * Re-enable rx framework.
4552116743Ssam		 */
4553116743Ssam		if (ath_startrecv(sc) != 0) {
4554178354Ssam			if_printf(ifp, "%s: unable to restart recv logic\n",
4555178354Ssam			    __func__);
4556116743Ssam			return EIO;
4557116743Ssam		}
4558116743Ssam
4559116743Ssam		/*
4560116743Ssam		 * Change channels and update the h/w rate map
4561116743Ssam		 * if we're switching; e.g. 11a to 11b/g.
4562116743Ssam		 */
4563138570Ssam		ath_chan_change(sc, chan);
4564119150Ssam
4565119150Ssam		/*
4566223568Sadrian		 * Reset clears the beacon timers; reset them
4567223568Sadrian		 * here if needed.
4568223568Sadrian		 */
4569223568Sadrian		if (sc->sc_beacons) {		/* restart beacons */
4570223568Sadrian#ifdef IEEE80211_SUPPORT_TDMA
4571223568Sadrian			if (sc->sc_tdma)
4572223568Sadrian				ath_tdma_config(sc, NULL);
4573223568Sadrian			else
4574223568Sadrian#endif
4575223568Sadrian			ath_beacon_config(sc, NULL);
4576223568Sadrian		}
4577223568Sadrian
4578223568Sadrian		/*
4579119150Ssam		 * Re-enable interrupts.
4580119150Ssam		 */
4581119150Ssam		ath_hal_intrset(ah, sc->sc_imask);
4582116743Ssam	}
4583116743Ssam	return 0;
4584116743Ssam}
4585116743Ssam
4586116743Ssam/*
4587116743Ssam * Periodically recalibrate the PHY to account
4588116743Ssam * for temperature/environment changes.
4589116743Ssam */
4590116743Ssamstatic void
4591116743Ssamath_calibrate(void *arg)
4592116743Ssam{
4593116743Ssam	struct ath_softc *sc = arg;
4594116743Ssam	struct ath_hal *ah = sc->sc_ah;
4595185744Ssam	struct ifnet *ifp = sc->sc_ifp;
4596187608Ssam	struct ieee80211com *ic = ifp->if_l2com;
4597185744Ssam	HAL_BOOL longCal, isCalDone;
4598217684Sadrian	HAL_BOOL aniCal, shortCal = AH_FALSE;
4599185744Ssam	int nextcal;
4600116743Ssam
4601187608Ssam	if (ic->ic_flags & IEEE80211_F_SCAN)	/* defer, off channel */
4602187608Ssam		goto restart;
4603185744Ssam	longCal = (ticks - sc->sc_lastlongcal >= ath_longcalinterval*hz);
4604217684Sadrian	aniCal = (ticks - sc->sc_lastani >= ath_anicalinterval*hz/1000);
4605217684Sadrian	if (sc->sc_doresetcal)
4606217684Sadrian		shortCal = (ticks - sc->sc_lastshortcal >= ath_shortcalinterval*hz/1000);
4607217684Sadrian
4608217684Sadrian	DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: shortCal=%d; longCal=%d; aniCal=%d\n", __func__, shortCal, longCal, aniCal);
4609217684Sadrian	if (aniCal) {
4610217684Sadrian		sc->sc_stats.ast_ani_cal++;
4611217684Sadrian		sc->sc_lastani = ticks;
4612217684Sadrian		ath_hal_ani_poll(ah, sc->sc_curchan);
4613217684Sadrian	}
4614217684Sadrian
4615185744Ssam	if (longCal) {
4616185744Ssam		sc->sc_stats.ast_per_cal++;
4617211136Sadrian		sc->sc_lastlongcal = ticks;
4618185744Ssam		if (ath_hal_getrfgain(ah) == HAL_RFGAIN_NEED_CHANGE) {
4619185744Ssam			/*
4620185744Ssam			 * Rfgain is out of bounds, reset the chip
4621185744Ssam			 * to load new gain values.
4622185744Ssam			 */
4623185744Ssam			DPRINTF(sc, ATH_DEBUG_CALIBRATE,
4624185744Ssam				"%s: rfgain change\n", __func__);
4625185744Ssam			sc->sc_stats.ast_per_rfgain++;
4626185744Ssam			ath_reset(ifp);
4627185744Ssam		}
4628116743Ssam		/*
4629185744Ssam		 * If this long cal is after an idle period, then
4630185744Ssam		 * reset the data collection state so we start fresh.
4631116743Ssam		 */
4632185744Ssam		if (sc->sc_resetcal) {
4633187831Ssam			(void) ath_hal_calreset(ah, sc->sc_curchan);
4634185744Ssam			sc->sc_lastcalreset = ticks;
4635217684Sadrian			sc->sc_lastshortcal = ticks;
4636185744Ssam			sc->sc_resetcal = 0;
4637217684Sadrian			sc->sc_doresetcal = AH_TRUE;
4638185744Ssam		}
4639116743Ssam	}
4640217684Sadrian
4641217684Sadrian	/* Only call if we're doing a short/long cal, not for ANI calibration */
4642217684Sadrian	if (shortCal || longCal) {
4643217684Sadrian		if (ath_hal_calibrateN(ah, sc->sc_curchan, longCal, &isCalDone)) {
4644217684Sadrian			if (longCal) {
4645217684Sadrian				/*
4646217684Sadrian				 * Calibrate noise floor data again in case of change.
4647217684Sadrian				 */
4648217684Sadrian				ath_hal_process_noisefloor(ah);
4649217684Sadrian			}
4650217684Sadrian		} else {
4651217684Sadrian			DPRINTF(sc, ATH_DEBUG_ANY,
4652217684Sadrian				"%s: calibration of channel %u failed\n",
4653217684Sadrian				__func__, sc->sc_curchan->ic_freq);
4654217684Sadrian			sc->sc_stats.ast_per_calfail++;
4655185744Ssam		}
4656217684Sadrian		if (shortCal)
4657217684Sadrian			sc->sc_lastshortcal = ticks;
4658116743Ssam	}
4659185744Ssam	if (!isCalDone) {
4660187608Ssamrestart:
4661185744Ssam		/*
4662185744Ssam		 * Use a shorter interval to potentially collect multiple
4663185744Ssam		 * data samples required to complete calibration.  Once
4664185744Ssam		 * we're told the work is done we drop back to a longer
4665185744Ssam		 * interval between requests.  We're more aggressive doing
4666185744Ssam		 * work when operating as an AP to improve operation right
4667185744Ssam		 * after startup.
4668185744Ssam		 */
4669217684Sadrian		sc->sc_lastshortcal = ticks;
4670217684Sadrian		nextcal = ath_shortcalinterval*hz/1000;
4671185744Ssam		if (sc->sc_opmode != HAL_M_HOSTAP)
4672185744Ssam			nextcal *= 10;
4673217684Sadrian		sc->sc_doresetcal = AH_TRUE;
4674185744Ssam	} else {
4675217684Sadrian		/* nextcal should be the shortest time for next event */
4676185744Ssam		nextcal = ath_longcalinterval*hz;
4677185744Ssam		if (sc->sc_lastcalreset == 0)
4678185744Ssam			sc->sc_lastcalreset = sc->sc_lastlongcal;
4679185744Ssam		else if (ticks - sc->sc_lastcalreset >= ath_resetcalinterval*hz)
4680185744Ssam			sc->sc_resetcal = 1;	/* setup reset next trip */
4681217684Sadrian		sc->sc_doresetcal = AH_FALSE;
4682155515Ssam	}
4683217684Sadrian	/* ANI calibration may occur more often than short/long/resetcal */
4684217684Sadrian	if (ath_anicalinterval > 0)
4685217684Sadrian		nextcal = MIN(nextcal, ath_anicalinterval*hz/1000);
4686155515Ssam
4687185744Ssam	if (nextcal != 0) {
4688185744Ssam		DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: next +%u (%sisCalDone)\n",
4689185744Ssam		    __func__, nextcal, isCalDone ? "" : "!");
4690185744Ssam		callout_reset(&sc->sc_cal_ch, nextcal, ath_calibrate, sc);
4691185744Ssam	} else {
4692185744Ssam		DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: calibration disabled\n",
4693185744Ssam		    __func__);
4694185744Ssam		/* NB: don't rearm timer */
4695185744Ssam	}
4696116743Ssam}
4697116743Ssam
4698170530Ssamstatic void
4699170530Ssamath_scan_start(struct ieee80211com *ic)
4700170530Ssam{
4701170530Ssam	struct ifnet *ifp = ic->ic_ifp;
4702170530Ssam	struct ath_softc *sc = ifp->if_softc;
4703170530Ssam	struct ath_hal *ah = sc->sc_ah;
4704170530Ssam	u_int32_t rfilt;
4705170530Ssam
4706170530Ssam	/* XXX calibration timer? */
4707170530Ssam
4708170530Ssam	sc->sc_scanning = 1;
4709170530Ssam	sc->sc_syncbeacon = 0;
4710170530Ssam	rfilt = ath_calcrxfilter(sc);
4711170530Ssam	ath_hal_setrxfilter(ah, rfilt);
4712170530Ssam	ath_hal_setassocid(ah, ifp->if_broadcastaddr, 0);
4713170530Ssam
4714170530Ssam	DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0\n",
4715170530Ssam		 __func__, rfilt, ether_sprintf(ifp->if_broadcastaddr));
4716170530Ssam}
4717170530Ssam
4718170530Ssamstatic void
4719170530Ssamath_scan_end(struct ieee80211com *ic)
4720170530Ssam{
4721170530Ssam	struct ifnet *ifp = ic->ic_ifp;
4722170530Ssam	struct ath_softc *sc = ifp->if_softc;
4723170530Ssam	struct ath_hal *ah = sc->sc_ah;
4724170530Ssam	u_int32_t rfilt;
4725170530Ssam
4726170530Ssam	sc->sc_scanning = 0;
4727170530Ssam	rfilt = ath_calcrxfilter(sc);
4728170530Ssam	ath_hal_setrxfilter(ah, rfilt);
4729170530Ssam	ath_hal_setassocid(ah, sc->sc_curbssid, sc->sc_curaid);
4730170530Ssam
4731170530Ssam	ath_hal_process_noisefloor(ah);
4732170530Ssam
4733170530Ssam	DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
4734170530Ssam		 __func__, rfilt, ether_sprintf(sc->sc_curbssid),
4735170530Ssam		 sc->sc_curaid);
4736170530Ssam}
4737170530Ssam
4738170530Ssamstatic void
4739170530Ssamath_set_channel(struct ieee80211com *ic)
4740170530Ssam{
4741170530Ssam	struct ifnet *ifp = ic->ic_ifp;
4742170530Ssam	struct ath_softc *sc = ifp->if_softc;
4743170530Ssam
4744170530Ssam	(void) ath_chan_set(sc, ic->ic_curchan);
4745170530Ssam	/*
4746170530Ssam	 * If we are returning to our bss channel then mark state
4747170530Ssam	 * so the next recv'd beacon's tsf will be used to sync the
4748170530Ssam	 * beacon timers.  Note that since we only hear beacons in
4749170530Ssam	 * sta/ibss mode this has no effect in other operating modes.
4750170530Ssam	 */
4751170530Ssam	if (!sc->sc_scanning && ic->ic_curchan == ic->ic_bsschan)
4752170530Ssam		sc->sc_syncbeacon = 1;
4753170530Ssam}
4754170530Ssam
4755204100Sdeischen/*
4756178354Ssam * Walk the vap list and check if there any vap's in RUN state.
4757178354Ssam */
4758116743Ssamstatic int
4759178354Ssamath_isanyrunningvaps(struct ieee80211vap *this)
4760116743Ssam{
4761178354Ssam	struct ieee80211com *ic = this->iv_ic;
4762178354Ssam	struct ieee80211vap *vap;
4763178354Ssam
4764178354Ssam	IEEE80211_LOCK_ASSERT(ic);
4765178354Ssam
4766178354Ssam	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
4767193389Ssam		if (vap != this && vap->iv_state >= IEEE80211_S_RUN)
4768178354Ssam			return 1;
4769178354Ssam	}
4770178354Ssam	return 0;
4771178354Ssam}
4772178354Ssam
4773178354Ssamstatic int
4774178354Ssamath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
4775178354Ssam{
4776178354Ssam	struct ieee80211com *ic = vap->iv_ic;
4777178354Ssam	struct ath_softc *sc = ic->ic_ifp->if_softc;
4778178354Ssam	struct ath_vap *avp = ATH_VAP(vap);
4779116743Ssam	struct ath_hal *ah = sc->sc_ah;
4780178354Ssam	struct ieee80211_node *ni = NULL;
4781170530Ssam	int i, error, stamode;
4782116743Ssam	u_int32_t rfilt;
4783223671Sadrian	int csa_run_transition = 0;
4784116743Ssam	static const HAL_LED_STATE leds[] = {
4785116743Ssam	    HAL_LED_INIT,	/* IEEE80211_S_INIT */
4786116743Ssam	    HAL_LED_SCAN,	/* IEEE80211_S_SCAN */
4787116743Ssam	    HAL_LED_AUTH,	/* IEEE80211_S_AUTH */
4788116743Ssam	    HAL_LED_ASSOC, 	/* IEEE80211_S_ASSOC */
4789172205Ssam	    HAL_LED_RUN, 	/* IEEE80211_S_CAC */
4790116743Ssam	    HAL_LED_RUN, 	/* IEEE80211_S_RUN */
4791172205Ssam	    HAL_LED_RUN, 	/* IEEE80211_S_CSA */
4792172205Ssam	    HAL_LED_RUN, 	/* IEEE80211_S_SLEEP */
4793116743Ssam	};
4794116743Ssam
4795138570Ssam	DPRINTF(sc, ATH_DEBUG_STATE, "%s: %s -> %s\n", __func__,
4796178354Ssam		ieee80211_state_name[vap->iv_state],
4797138570Ssam		ieee80211_state_name[nstate]);
4798116743Ssam
4799223671Sadrian	if (vap->iv_state == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN)
4800223671Sadrian		csa_run_transition = 1;
4801223671Sadrian
4802189605Ssam	callout_drain(&sc->sc_cal_ch);
4803116743Ssam	ath_hal_setledstate(ah, leds[nstate]);	/* set LED */
4804116743Ssam
4805178354Ssam	if (nstate == IEEE80211_S_SCAN) {
4806138570Ssam		/*
4807178354Ssam		 * Scanning: turn off beacon miss and don't beacon.
4808178354Ssam		 * Mark beacon state so when we reach RUN state we'll
4809178354Ssam		 * [re]setup beacons.  Unblock the task q thread so
4810178354Ssam		 * deferred interrupt processing is done.
4811140436Ssam		 */
4812178354Ssam		ath_hal_intrset(ah,
4813178354Ssam		    sc->sc_imask &~ (HAL_INT_SWBA | HAL_INT_BMISS));
4814170104Ssam		sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
4815178354Ssam		sc->sc_beacons = 0;
4816178354Ssam		taskqueue_unblock(sc->sc_tq);
4817116743Ssam	}
4818170530Ssam
4819178354Ssam	ni = vap->iv_bss;
4820170530Ssam	rfilt = ath_calcrxfilter(sc);
4821178354Ssam	stamode = (vap->iv_opmode == IEEE80211_M_STA ||
4822184361Ssam		   vap->iv_opmode == IEEE80211_M_AHDEMO ||
4823178354Ssam		   vap->iv_opmode == IEEE80211_M_IBSS);
4824170530Ssam	if (stamode && nstate == IEEE80211_S_RUN) {
4825170530Ssam		sc->sc_curaid = ni->ni_associd;
4826170530Ssam		IEEE80211_ADDR_COPY(sc->sc_curbssid, ni->ni_bssid);
4827178354Ssam		ath_hal_setassocid(ah, sc->sc_curbssid, sc->sc_curaid);
4828178354Ssam	}
4829170530Ssam	DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
4830178354Ssam	   __func__, rfilt, ether_sprintf(sc->sc_curbssid), sc->sc_curaid);
4831116743Ssam	ath_hal_setrxfilter(ah, rfilt);
4832116743Ssam
4833178354Ssam	/* XXX is this to restore keycache on resume? */
4834178354Ssam	if (vap->iv_opmode != IEEE80211_M_STA &&
4835178354Ssam	    (vap->iv_flags & IEEE80211_F_PRIVACY)) {
4836116743Ssam		for (i = 0; i < IEEE80211_WEP_NKID; i++)
4837116743Ssam			if (ath_hal_keyisvalid(ah, i))
4838170530Ssam				ath_hal_keysetmac(ah, i, ni->ni_bssid);
4839116743Ssam	}
4840138570Ssam
4841178354Ssam	/*
4842178354Ssam	 * Invoke the parent method to do net80211 work.
4843178354Ssam	 */
4844178354Ssam	error = avp->av_newstate(vap, nstate, arg);
4845178354Ssam	if (error != 0)
4846178354Ssam		goto bad;
4847178354Ssam
4848170530Ssam	if (nstate == IEEE80211_S_RUN) {
4849178354Ssam		/* NB: collect bss node again, it may have changed */
4850178354Ssam		ni = vap->iv_bss;
4851178354Ssam
4852138570Ssam		DPRINTF(sc, ATH_DEBUG_STATE,
4853178354Ssam		    "%s(RUN): iv_flags 0x%08x bintvl %d bssid %s "
4854178354Ssam		    "capinfo 0x%04x chan %d\n", __func__,
4855178354Ssam		    vap->iv_flags, ni->ni_intval, ether_sprintf(ni->ni_bssid),
4856178354Ssam		    ni->ni_capinfo, ieee80211_chan2ieee(ic, ic->ic_curchan));
4857116743Ssam
4858178354Ssam		switch (vap->iv_opmode) {
4859190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
4860186904Ssam		case IEEE80211_M_AHDEMO:
4861186904Ssam			if ((vap->iv_caps & IEEE80211_C_TDMA) == 0)
4862186904Ssam				break;
4863186904Ssam			/* fall thru... */
4864186904Ssam#endif
4865147057Ssam		case IEEE80211_M_HOSTAP:
4866147057Ssam		case IEEE80211_M_IBSS:
4867195618Srpaulo		case IEEE80211_M_MBSS:
4868140759Ssam			/*
4869147057Ssam			 * Allocate and setup the beacon frame.
4870147057Ssam			 *
4871140759Ssam			 * Stop any previous beacon DMA.  This may be
4872140759Ssam			 * necessary, for example, when an ibss merge
4873140759Ssam			 * causes reconfiguration; there will be a state
4874140759Ssam			 * transition from RUN->RUN that means we may
4875140759Ssam			 * be called with beacon transmission active.
4876140759Ssam			 */
4877140759Ssam			ath_hal_stoptxdma(ah, sc->sc_bhalq);
4878178354Ssam
4879116743Ssam			error = ath_beacon_alloc(sc, ni);
4880116743Ssam			if (error != 0)
4881116743Ssam				goto bad;
4882155490Ssam			/*
4883155496Ssam			 * If joining an adhoc network defer beacon timer
4884155496Ssam			 * configuration to the next beacon frame so we
4885155496Ssam			 * have a current TSF to use.  Otherwise we're
4886178354Ssam			 * starting an ibss/bss so there's no need to delay;
4887178354Ssam			 * if this is the first vap moving to RUN state, then
4888178354Ssam			 * beacon state needs to be [re]configured.
4889155490Ssam			 */
4890178354Ssam			if (vap->iv_opmode == IEEE80211_M_IBSS &&
4891178354Ssam			    ni->ni_tstamp.tsf != 0) {
4892155496Ssam				sc->sc_syncbeacon = 1;
4893178354Ssam			} else if (!sc->sc_beacons) {
4894190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
4895186904Ssam				if (vap->iv_caps & IEEE80211_C_TDMA)
4896186904Ssam					ath_tdma_config(sc, vap);
4897186904Ssam				else
4898186904Ssam#endif
4899186904Ssam					ath_beacon_config(sc, vap);
4900178354Ssam				sc->sc_beacons = 1;
4901178354Ssam			}
4902147057Ssam			break;
4903147057Ssam		case IEEE80211_M_STA:
4904147057Ssam			/*
4905155496Ssam			 * Defer beacon timer configuration to the next
4906155496Ssam			 * beacon frame so we have a current TSF to use
4907155496Ssam			 * (any TSF collected when scanning is likely old).
4908223671Sadrian			 * However if it's due to a CSA -> RUN transition,
4909223671Sadrian			 * force a beacon update so we pick up a lack of
4910223671Sadrian			 * beacons from an AP in CAC and thus force a
4911223671Sadrian			 * scan.
4912155490Ssam			 */
4913155496Ssam			sc->sc_syncbeacon = 1;
4914223671Sadrian			if (csa_run_transition)
4915223671Sadrian				ath_beacon_config(sc, vap);
4916147057Ssam			break;
4917178354Ssam		case IEEE80211_M_MONITOR:
4918178354Ssam			/*
4919178354Ssam			 * Monitor mode vaps have only INIT->RUN and RUN->RUN
4920178354Ssam			 * transitions so we must re-enable interrupts here to
4921178354Ssam			 * handle the case of a single monitor mode vap.
4922178354Ssam			 */
4923178354Ssam			ath_hal_intrset(ah, sc->sc_imask);
4924178354Ssam			break;
4925178354Ssam		case IEEE80211_M_WDS:
4926178354Ssam			break;
4927147057Ssam		default:
4928147057Ssam			break;
4929116743Ssam		}
4930116743Ssam		/*
4931154140Ssam		 * Let the hal process statistics collected during a
4932154140Ssam		 * scan so it can provide calibrated noise floor data.
4933154140Ssam		 */
4934154140Ssam		ath_hal_process_noisefloor(ah);
4935154140Ssam		/*
4936155485Ssam		 * Reset rssi stats; maybe not the best place...
4937155485Ssam		 */
4938155485Ssam		sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
4939155485Ssam		sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
4940155485Ssam		sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
4941178354Ssam		/*
4942178354Ssam		 * Finally, start any timers and the task q thread
4943178354Ssam		 * (in case we didn't go through SCAN state).
4944178354Ssam		 */
4945185744Ssam		if (ath_longcalinterval != 0) {
4946178354Ssam			/* start periodic recalibration timer */
4947185744Ssam			callout_reset(&sc->sc_cal_ch, 1, ath_calibrate, sc);
4948185744Ssam		} else {
4949185744Ssam			DPRINTF(sc, ATH_DEBUG_CALIBRATE,
4950185744Ssam			    "%s: calibration disabled\n", __func__);
4951178354Ssam		}
4952178354Ssam		taskqueue_unblock(sc->sc_tq);
4953178354Ssam	} else if (nstate == IEEE80211_S_INIT) {
4954178354Ssam		/*
4955178354Ssam		 * If there are no vaps left in RUN state then
4956178354Ssam		 * shutdown host/driver operation:
4957178354Ssam		 * o disable interrupts
4958178354Ssam		 * o disable the task queue thread
4959178354Ssam		 * o mark beacon processing as stopped
4960178354Ssam		 */
4961178354Ssam		if (!ath_isanyrunningvaps(vap)) {
4962178354Ssam			sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
4963178354Ssam			/* disable interrupts  */
4964178354Ssam			ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL);
4965178354Ssam			taskqueue_block(sc->sc_tq);
4966178354Ssam			sc->sc_beacons = 0;
4967178354Ssam		}
4968190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
4969186904Ssam		ath_hal_setcca(ah, AH_TRUE);
4970186904Ssam#endif
4971116743Ssam	}
4972116743Ssambad:
4973116743Ssam	return error;
4974116743Ssam}
4975116743Ssam
4976116743Ssam/*
4977147057Ssam * Allocate a key cache slot to the station so we can
4978147057Ssam * setup a mapping from key index to node. The key cache
4979147057Ssam * slot is needed for managing antenna state and for
4980147057Ssam * compression when stations do not use crypto.  We do
4981147057Ssam * it uniliaterally here; if crypto is employed this slot
4982147057Ssam * will be reassigned.
4983147057Ssam */
4984147057Ssamstatic void
4985147057Ssamath_setup_stationkey(struct ieee80211_node *ni)
4986147057Ssam{
4987178354Ssam	struct ieee80211vap *vap = ni->ni_vap;
4988178354Ssam	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
4989148863Ssam	ieee80211_keyix keyix, rxkeyix;
4990147057Ssam
4991178354Ssam	if (!ath_key_alloc(vap, &ni->ni_ucastkey, &keyix, &rxkeyix)) {
4992147057Ssam		/*
4993147057Ssam		 * Key cache is full; we'll fall back to doing
4994147057Ssam		 * the more expensive lookup in software.  Note
4995147057Ssam		 * this also means no h/w compression.
4996147057Ssam		 */
4997147057Ssam		/* XXX msg+statistic */
4998147057Ssam	} else {
4999148863Ssam		/* XXX locking? */
5000147057Ssam		ni->ni_ucastkey.wk_keyix = keyix;
5001148863Ssam		ni->ni_ucastkey.wk_rxkeyix = rxkeyix;
5002188447Ssam		/* NB: must mark device key to get called back on delete */
5003188447Ssam		ni->ni_ucastkey.wk_flags |= IEEE80211_KEY_DEVKEY;
5004179401Ssam		IEEE80211_ADDR_COPY(ni->ni_ucastkey.wk_macaddr, ni->ni_macaddr);
5005147057Ssam		/* NB: this will create a pass-thru key entry */
5006179401Ssam		ath_keyset(sc, &ni->ni_ucastkey, vap->iv_bss);
5007147057Ssam	}
5008147057Ssam}
5009147057Ssam
5010147057Ssam/*
5011116743Ssam * Setup driver-specific state for a newly associated node.
5012116743Ssam * Note that we're called also on a re-associate, the isnew
5013116743Ssam * param tells us if this is the first time or not.
5014116743Ssam */
5015116743Ssamstatic void
5016148307Ssamath_newassoc(struct ieee80211_node *ni, int isnew)
5017116743Ssam{
5018178354Ssam	struct ath_node *an = ATH_NODE(ni);
5019178354Ssam	struct ieee80211vap *vap = ni->ni_vap;
5020178354Ssam	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
5021184347Ssam	const struct ieee80211_txparam *tp = ni->ni_txparms;
5022116743Ssam
5023191866Ssam	an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate);
5024191866Ssam	an->an_mgmtrix = ath_tx_findrix(sc, tp->mgmtrate);
5025178354Ssam
5026178354Ssam	ath_rate_newassoc(sc, an, isnew);
5027204100Sdeischen	if (isnew &&
5028178354Ssam	    (vap->iv_flags & IEEE80211_F_PRIVACY) == 0 && sc->sc_hasclrkey &&
5029178354Ssam	    ni->ni_ucastkey.wk_keyix == IEEE80211_KEYIX_NONE)
5030147057Ssam		ath_setup_stationkey(ni);
5031116743Ssam}
5032116743Ssam
5033116743Ssamstatic int
5034187831Ssamath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *reg,
5035178354Ssam	int nchans, struct ieee80211_channel chans[])
5036178354Ssam{
5037178354Ssam	struct ath_softc *sc = ic->ic_ifp->if_softc;
5038178354Ssam	struct ath_hal *ah = sc->sc_ah;
5039187831Ssam	HAL_STATUS status;
5040178354Ssam
5041184355Ssam	DPRINTF(sc, ATH_DEBUG_REGDOMAIN,
5042187831Ssam	    "%s: rd %u cc %u location %c%s\n",
5043187831Ssam	    __func__, reg->regdomain, reg->country, reg->location,
5044187831Ssam	    reg->ecm ? " ecm" : "");
5045184355Ssam
5046187831Ssam	status = ath_hal_set_channels(ah, chans, nchans,
5047187831Ssam	    reg->country, reg->regdomain);
5048187831Ssam	if (status != HAL_OK) {
5049187831Ssam		DPRINTF(sc, ATH_DEBUG_REGDOMAIN, "%s: failed, status %u\n",
5050187831Ssam		    __func__, status);
5051187831Ssam		return EINVAL;		/* XXX */
5052178354Ssam	}
5053224716Sadrian
5054116743Ssam	return 0;
5055116743Ssam}
5056116743Ssam
5057138570Ssamstatic void
5058178354Ssamath_getradiocaps(struct ieee80211com *ic,
5059187800Ssam	int maxchans, int *nchans, struct ieee80211_channel chans[])
5060178354Ssam{
5061178354Ssam	struct ath_softc *sc = ic->ic_ifp->if_softc;
5062178354Ssam	struct ath_hal *ah = sc->sc_ah;
5063178354Ssam
5064187831Ssam	DPRINTF(sc, ATH_DEBUG_REGDOMAIN, "%s: use rd %u cc %d\n",
5065187831Ssam	    __func__, SKU_DEBUG, CTRY_DEFAULT);
5066184355Ssam
5067187831Ssam	/* XXX check return */
5068187831Ssam	(void) ath_hal_getchannels(ah, chans, maxchans, nchans,
5069187831Ssam	    HAL_MODE_ALL, CTRY_DEFAULT, SKU_DEBUG, AH_TRUE);
5070184355Ssam
5071178354Ssam}
5072178354Ssam
5073178354Ssamstatic int
5074178354Ssamath_getchannels(struct ath_softc *sc)
5075178354Ssam{
5076178354Ssam	struct ifnet *ifp = sc->sc_ifp;
5077178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
5078178354Ssam	struct ath_hal *ah = sc->sc_ah;
5079187831Ssam	HAL_STATUS status;
5080178354Ssam
5081178354Ssam	/*
5082187831Ssam	 * Collect channel set based on EEPROM contents.
5083178354Ssam	 */
5084187831Ssam	status = ath_hal_init_channels(ah, ic->ic_channels, IEEE80211_CHAN_MAX,
5085187831Ssam	    &ic->ic_nchans, HAL_MODE_ALL, CTRY_DEFAULT, SKU_NONE, AH_TRUE);
5086187831Ssam	if (status != HAL_OK) {
5087187831Ssam		if_printf(ifp, "%s: unable to collect channel list from hal, "
5088187831Ssam		    "status %d\n", __func__, status);
5089187831Ssam		return EINVAL;
5090187831Ssam	}
5091178751Ssam	(void) ath_hal_getregdomain(ah, &sc->sc_eerd);
5092178751Ssam	ath_hal_getcountrycode(ah, &sc->sc_eecc);	/* NB: cannot fail */
5093187831Ssam	/* XXX map Atheros sku's to net80211 SKU's */
5094187831Ssam	/* XXX net80211 types too small */
5095187831Ssam	ic->ic_regdomain.regdomain = (uint16_t) sc->sc_eerd;
5096187831Ssam	ic->ic_regdomain.country = (uint16_t) sc->sc_eecc;
5097187831Ssam	ic->ic_regdomain.isocc[0] = ' ';	/* XXX don't know */
5098187831Ssam	ic->ic_regdomain.isocc[1] = ' ';
5099187831Ssam
5100178354Ssam	ic->ic_regdomain.ecm = 1;
5101178354Ssam	ic->ic_regdomain.location = 'I';
5102184355Ssam
5103184355Ssam	DPRINTF(sc, ATH_DEBUG_REGDOMAIN,
5104187831Ssam	    "%s: eeprom rd %u cc %u (mapped rd %u cc %u) location %c%s\n",
5105184355Ssam	    __func__, sc->sc_eerd, sc->sc_eecc,
5106184355Ssam	    ic->ic_regdomain.regdomain, ic->ic_regdomain.country,
5107187831Ssam	    ic->ic_regdomain.location, ic->ic_regdomain.ecm ? " ecm" : "");
5108178354Ssam	return 0;
5109178354Ssam}
5110178354Ssam
5111178354Ssamstatic void
5112140432Ssamath_led_done(void *arg)
5113138570Ssam{
5114140432Ssam	struct ath_softc *sc = arg;
5115138570Ssam
5116140432Ssam	sc->sc_blinking = 0;
5117140432Ssam}
5118140432Ssam
5119140432Ssam/*
5120140432Ssam * Turn the LED off: flip the pin and then set a timer so no
5121140432Ssam * update will happen for the specified duration.
5122140432Ssam */
5123140432Ssamstatic void
5124140432Ssamath_led_off(void *arg)
5125140432Ssam{
5126140432Ssam	struct ath_softc *sc = arg;
5127140432Ssam
5128140432Ssam	ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon);
5129140432Ssam	callout_reset(&sc->sc_ledtimer, sc->sc_ledoff, ath_led_done, sc);
5130140432Ssam}
5131140432Ssam
5132140432Ssam/*
5133140432Ssam * Blink the LED according to the specified on/off times.
5134140432Ssam */
5135140432Ssamstatic void
5136140432Ssamath_led_blink(struct ath_softc *sc, int on, int off)
5137140432Ssam{
5138140432Ssam	DPRINTF(sc, ATH_DEBUG_LED, "%s: on %u off %u\n", __func__, on, off);
5139140432Ssam	ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, sc->sc_ledon);
5140140432Ssam	sc->sc_blinking = 1;
5141140432Ssam	sc->sc_ledoff = off;
5142140432Ssam	callout_reset(&sc->sc_ledtimer, on, ath_led_off, sc);
5143140432Ssam}
5144140432Ssam
5145140432Ssamstatic void
5146184368Ssamath_led_event(struct ath_softc *sc, int rix)
5147140432Ssam{
5148140432Ssam	sc->sc_ledevent = ticks;	/* time of last event */
5149140432Ssam	if (sc->sc_blinking)		/* don't interrupt active blink */
5150140432Ssam		return;
5151184368Ssam	ath_led_blink(sc, sc->sc_hwmap[rix].ledon, sc->sc_hwmap[rix].ledoff);
5152138570Ssam}
5153138570Ssam
5154116743Ssamstatic int
5155116743Ssamath_rate_setup(struct ath_softc *sc, u_int mode)
5156116743Ssam{
5157116743Ssam	struct ath_hal *ah = sc->sc_ah;
5158116743Ssam	const HAL_RATE_TABLE *rt;
5159116743Ssam
5160116743Ssam	switch (mode) {
5161116743Ssam	case IEEE80211_MODE_11A:
5162155488Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_11A);
5163116743Ssam		break;
5164166013Ssam	case IEEE80211_MODE_HALF:
5165165571Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE);
5166165571Ssam		break;
5167166013Ssam	case IEEE80211_MODE_QUARTER:
5168165571Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE);
5169165571Ssam		break;
5170116743Ssam	case IEEE80211_MODE_11B:
5171155488Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_11B);
5172116743Ssam		break;
5173116743Ssam	case IEEE80211_MODE_11G:
5174155488Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_11G);
5175116743Ssam		break;
5176138570Ssam	case IEEE80211_MODE_TURBO_A:
5177170530Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_108A);
5178116743Ssam		break;
5179138570Ssam	case IEEE80211_MODE_TURBO_G:
5180155488Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_108G);
5181138570Ssam		break;
5182170530Ssam	case IEEE80211_MODE_STURBO_A:
5183170530Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_TURBO);
5184170530Ssam		break;
5185170530Ssam	case IEEE80211_MODE_11NA:
5186170530Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_11NA_HT20);
5187170530Ssam		break;
5188170530Ssam	case IEEE80211_MODE_11NG:
5189170530Ssam		rt = ath_hal_getratetable(ah, HAL_MODE_11NG_HT20);
5190170530Ssam		break;
5191116743Ssam	default:
5192138570Ssam		DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid mode %u\n",
5193138570Ssam			__func__, mode);
5194116743Ssam		return 0;
5195116743Ssam	}
5196155488Ssam	sc->sc_rates[mode] = rt;
5197165571Ssam	return (rt != NULL);
5198116743Ssam}
5199116743Ssam
5200116743Ssamstatic void
5201116743Ssamath_setcurmode(struct ath_softc *sc, enum ieee80211_phymode mode)
5202116743Ssam{
5203140432Ssam#define	N(a)	(sizeof(a)/sizeof(a[0]))
5204140432Ssam	/* NB: on/off times from the Atheros NDIS driver, w/ permission */
5205140432Ssam	static const struct {
5206140432Ssam		u_int		rate;		/* tx/rx 802.11 rate */
5207140432Ssam		u_int16_t	timeOn;		/* LED on time (ms) */
5208140432Ssam		u_int16_t	timeOff;	/* LED off time (ms) */
5209140432Ssam	} blinkrates[] = {
5210140432Ssam		{ 108,  40,  10 },
5211140432Ssam		{  96,  44,  11 },
5212140432Ssam		{  72,  50,  13 },
5213140432Ssam		{  48,  57,  14 },
5214140432Ssam		{  36,  67,  16 },
5215140432Ssam		{  24,  80,  20 },
5216140432Ssam		{  22, 100,  25 },
5217140432Ssam		{  18, 133,  34 },
5218140432Ssam		{  12, 160,  40 },
5219140432Ssam		{  10, 200,  50 },
5220140432Ssam		{   6, 240,  58 },
5221140432Ssam		{   4, 267,  66 },
5222140432Ssam		{   2, 400, 100 },
5223140432Ssam		{   0, 500, 130 },
5224166013Ssam		/* XXX half/quarter rates */
5225140432Ssam	};
5226116743Ssam	const HAL_RATE_TABLE *rt;
5227140432Ssam	int i, j;
5228116743Ssam
5229116743Ssam	memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap));
5230116743Ssam	rt = sc->sc_rates[mode];
5231116743Ssam	KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode));
5232184365Ssam	for (i = 0; i < rt->rateCount; i++) {
5233184365Ssam		uint8_t ieeerate = rt->info[i].dot11Rate & IEEE80211_RATE_VAL;
5234184365Ssam		if (rt->info[i].phy != IEEE80211_T_HT)
5235184365Ssam			sc->sc_rixmap[ieeerate] = i;
5236184365Ssam		else
5237184365Ssam			sc->sc_rixmap[ieeerate | IEEE80211_RATE_MCS] = i;
5238184365Ssam	}
5239119144Ssam	memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
5240184368Ssam	for (i = 0; i < N(sc->sc_hwmap); i++) {
5241184368Ssam		if (i >= rt->rateCount) {
5242140432Ssam			sc->sc_hwmap[i].ledon = (500 * hz) / 1000;
5243140432Ssam			sc->sc_hwmap[i].ledoff = (130 * hz) / 1000;
5244139500Ssam			continue;
5245140432Ssam		}
5246140432Ssam		sc->sc_hwmap[i].ieeerate =
5247184368Ssam			rt->info[i].dot11Rate & IEEE80211_RATE_VAL;
5248184368Ssam		if (rt->info[i].phy == IEEE80211_T_HT)
5249184366Ssam			sc->sc_hwmap[i].ieeerate |= IEEE80211_RATE_MCS;
5250140761Ssam		sc->sc_hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
5251184368Ssam		if (rt->info[i].shortPreamble ||
5252184368Ssam		    rt->info[i].phy == IEEE80211_T_OFDM)
5253140761Ssam			sc->sc_hwmap[i].txflags |= IEEE80211_RADIOTAP_F_SHORTPRE;
5254192468Ssam		sc->sc_hwmap[i].rxflags = sc->sc_hwmap[i].txflags;
5255140432Ssam		for (j = 0; j < N(blinkrates)-1; j++)
5256140432Ssam			if (blinkrates[j].rate == sc->sc_hwmap[i].ieeerate)
5257140432Ssam				break;
5258140432Ssam		/* NB: this uses the last entry if the rate isn't found */
5259140432Ssam		/* XXX beware of overlow */
5260140432Ssam		sc->sc_hwmap[i].ledon = (blinkrates[j].timeOn * hz) / 1000;
5261140432Ssam		sc->sc_hwmap[i].ledoff = (blinkrates[j].timeOff * hz) / 1000;
5262138570Ssam	}
5263116743Ssam	sc->sc_currates = rt;
5264116743Ssam	sc->sc_curmode = mode;
5265138570Ssam	/*
5266138570Ssam	 * All protection frames are transmited at 2Mb/s for
5267138570Ssam	 * 11g, otherwise at 1Mb/s.
5268138570Ssam	 */
5269155484Ssam	if (mode == IEEE80211_MODE_11G)
5270191866Ssam		sc->sc_protrix = ath_tx_findrix(sc, 2*2);
5271155484Ssam	else
5272191866Ssam		sc->sc_protrix = ath_tx_findrix(sc, 2*1);
5273204100Sdeischen	/* NB: caller is responsible for resetting rate control state */
5274140432Ssam#undef N
5275116743Ssam}
5276116743Ssam
5277116743Ssamstatic void
5278189605Ssamath_watchdog(void *arg)
5279138570Ssam{
5280189605Ssam	struct ath_softc *sc = arg;
5281116743Ssam
5282189605Ssam	if (sc->sc_wd_timer != 0 && --sc->sc_wd_timer == 0) {
5283189605Ssam		struct ifnet *ifp = sc->sc_ifp;
5284185480Ssam		uint32_t hangs;
5285185480Ssam
5286185480Ssam		if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) &&
5287185480Ssam		    hangs != 0) {
5288185480Ssam			if_printf(ifp, "%s hang detected (0x%x)\n",
5289204100Sdeischen			    hangs & 0xff ? "bb" : "mac", hangs);
5290185480Ssam		} else
5291185480Ssam			if_printf(ifp, "device timeout\n");
5292170530Ssam		ath_reset(ifp);
5293170530Ssam		ifp->if_oerrors++;
5294170530Ssam		sc->sc_stats.ast_watchdog++;
5295138570Ssam	}
5296189605Ssam	callout_schedule(&sc->sc_wd_ch, hz);
5297138570Ssam}
5298138570Ssam
5299157438Ssam#ifdef ATH_DIAGAPI
5300138570Ssam/*
5301138570Ssam * Diagnostic interface to the HAL.  This is used by various
5302138570Ssam * tools to do things like retrieve register contents for
5303138570Ssam * debugging.  The mechanism is intentionally opaque so that
5304138570Ssam * it can change frequently w/o concern for compatiblity.
5305138570Ssam */
5306138570Ssamstatic int
5307138570Ssamath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad)
5308138570Ssam{
5309138570Ssam	struct ath_hal *ah = sc->sc_ah;
5310138570Ssam	u_int id = ad->ad_id & ATH_DIAG_ID;
5311138570Ssam	void *indata = NULL;
5312138570Ssam	void *outdata = NULL;
5313138570Ssam	u_int32_t insize = ad->ad_in_size;
5314138570Ssam	u_int32_t outsize = ad->ad_out_size;
5315138570Ssam	int error = 0;
5316138570Ssam
5317138570Ssam	if (ad->ad_id & ATH_DIAG_IN) {
5318121056Ssam		/*
5319138570Ssam		 * Copy in data.
5320121056Ssam		 */
5321138570Ssam		indata = malloc(insize, M_TEMP, M_NOWAIT);
5322138570Ssam		if (indata == NULL) {
5323138570Ssam			error = ENOMEM;
5324138570Ssam			goto bad;
5325116743Ssam		}
5326138570Ssam		error = copyin(ad->ad_in_data, indata, insize);
5327138570Ssam		if (error)
5328138570Ssam			goto bad;
5329116743Ssam	}
5330138570Ssam	if (ad->ad_id & ATH_DIAG_DYN) {
5331138570Ssam		/*
5332138570Ssam		 * Allocate a buffer for the results (otherwise the HAL
5333138570Ssam		 * returns a pointer to a buffer where we can read the
5334138570Ssam		 * results).  Note that we depend on the HAL leaving this
5335138570Ssam		 * pointer for us to use below in reclaiming the buffer;
5336138570Ssam		 * may want to be more defensive.
5337138570Ssam		 */
5338138570Ssam		outdata = malloc(outsize, M_TEMP, M_NOWAIT);
5339138570Ssam		if (outdata == NULL) {
5340138570Ssam			error = ENOMEM;
5341138570Ssam			goto bad;
5342138570Ssam		}
5343138570Ssam	}
5344138570Ssam	if (ath_hal_getdiagstate(ah, id, indata, insize, &outdata, &outsize)) {
5345138570Ssam		if (outsize < ad->ad_out_size)
5346138570Ssam			ad->ad_out_size = outsize;
5347138570Ssam		if (outdata != NULL)
5348138570Ssam			error = copyout(outdata, ad->ad_out_data,
5349138570Ssam					ad->ad_out_size);
5350121056Ssam	} else {
5351138570Ssam		error = EINVAL;
5352121056Ssam	}
5353138570Ssambad:
5354138570Ssam	if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
5355138570Ssam		free(indata, M_TEMP);
5356138570Ssam	if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
5357138570Ssam		free(outdata, M_TEMP);
5358138570Ssam	return error;
5359116743Ssam}
5360157438Ssam#endif /* ATH_DIAGAPI */
5361116743Ssam
5362138570Ssamstatic int
5363138570Ssamath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
5364116743Ssam{
5365138570Ssam#define	IS_RUNNING(ifp) \
5366148887Srwatson	((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
5367138570Ssam	struct ath_softc *sc = ifp->if_softc;
5368178354Ssam	struct ieee80211com *ic = ifp->if_l2com;
5369138570Ssam	struct ifreq *ifr = (struct ifreq *)data;
5370184358Ssam	const HAL_RATE_TABLE *rt;
5371138570Ssam	int error = 0;
5372116743Ssam
5373138570Ssam	switch (cmd) {
5374138570Ssam	case SIOCSIFFLAGS:
5375178704Sthompsa		ATH_LOCK(sc);
5376138570Ssam		if (IS_RUNNING(ifp)) {
5377138570Ssam			/*
5378138570Ssam			 * To avoid rescanning another access point,
5379138570Ssam			 * do not call ath_init() here.  Instead,
5380138570Ssam			 * only reflect promisc mode settings.
5381138570Ssam			 */
5382138570Ssam			ath_mode_init(sc);
5383138570Ssam		} else if (ifp->if_flags & IFF_UP) {
5384138570Ssam			/*
5385138570Ssam			 * Beware of being called during attach/detach
5386138570Ssam			 * to reset promiscuous mode.  In that case we
5387138570Ssam			 * will still be marked UP but not RUNNING.
5388138570Ssam			 * However trying to re-init the interface
5389138570Ssam			 * is the wrong thing to do as we've already
5390138570Ssam			 * torn down much of our state.  There's
5391138570Ssam			 * probably a better way to deal with this.
5392138570Ssam			 */
5393178354Ssam			if (!sc->sc_invalid)
5394147256Sbrooks				ath_init(sc);	/* XXX lose error */
5395179401Ssam		} else {
5396138570Ssam			ath_stop_locked(ifp);
5397179401Ssam#ifdef notyet
5398179401Ssam			/* XXX must wakeup in places like ath_vap_delete */
5399179401Ssam			if (!sc->sc_invalid)
5400179401Ssam				ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
5401179401Ssam#endif
5402179401Ssam		}
5403178704Sthompsa		ATH_UNLOCK(sc);
5404116743Ssam		break;
5405178354Ssam	case SIOCGIFMEDIA:
5406178354Ssam	case SIOCSIFMEDIA:
5407178354Ssam		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
5408178354Ssam		break;
5409138570Ssam	case SIOCGATHSTATS:
5410138570Ssam		/* NB: embed these numbers to get a consistent view */
5411138570Ssam		sc->sc_stats.ast_tx_packets = ifp->if_opackets;
5412138570Ssam		sc->sc_stats.ast_rx_packets = ifp->if_ipackets;
5413184358Ssam		sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi);
5414184358Ssam		sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi);
5415190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
5416186904Ssam		sc->sc_stats.ast_tdma_tsfadjp = TDMA_AVG(sc->sc_avgtsfdeltap);
5417186904Ssam		sc->sc_stats.ast_tdma_tsfadjm = TDMA_AVG(sc->sc_avgtsfdeltam);
5418186904Ssam#endif
5419184358Ssam		rt = sc->sc_currates;
5420184368Ssam		sc->sc_stats.ast_tx_rate =
5421184368Ssam		    rt->info[sc->sc_txrix].dot11Rate &~ IEEE80211_RATE_BASIC;
5422219891Sadrian		if (rt->info[sc->sc_txrix].phy & IEEE80211_T_HT)
5423219891Sadrian			sc->sc_stats.ast_tx_rate |= IEEE80211_RATE_MCS;
5424138570Ssam		return copyout(&sc->sc_stats,
5425178704Sthompsa		    ifr->ifr_data, sizeof (sc->sc_stats));
5426188557Ssam	case SIOCZATHSTATS:
5427188557Ssam		error = priv_check(curthread, PRIV_DRIVER);
5428188557Ssam		if (error == 0)
5429188557Ssam			memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
5430188557Ssam		break;
5431157438Ssam#ifdef ATH_DIAGAPI
5432138570Ssam	case SIOCGATHDIAG:
5433138570Ssam		error = ath_ioctl_diag(sc, (struct ath_diag *) ifr);
5434138570Ssam		break;
5435224245Sadrian	case SIOCGATHPHYERR:
5436224245Sadrian		error = ath_ioctl_phyerr(sc,(struct ath_diag*) ifr);
5437224245Sadrian		break;
5438157438Ssam#endif
5439178704Sthompsa	case SIOCGIFADDR:
5440178354Ssam		error = ether_ioctl(ifp, cmd, data);
5441116743Ssam		break;
5442178704Sthompsa	default:
5443178704Sthompsa		error = EINVAL;
5444178704Sthompsa		break;
5445116743Ssam	}
5446138570Ssam	return error;
5447139501Ssam#undef IS_RUNNING
5448138570Ssam}
5449116743Ssam
5450138570Ssam/*
5451138570Ssam * Announce various information on device/driver attach.
5452138570Ssam */
5453138570Ssamstatic void
5454138570Ssamath_announce(struct ath_softc *sc)
5455138570Ssam{
5456147256Sbrooks	struct ifnet *ifp = sc->sc_ifp;
5457138570Ssam	struct ath_hal *ah = sc->sc_ah;
5458138570Ssam
5459188968Ssam	if_printf(ifp, "AR%s mac %d.%d RF%s phy %d.%d\n",
5460188968Ssam		ath_hal_mac_name(ah), ah->ah_macVersion, ah->ah_macRev,
5461188968Ssam		ath_hal_rf_name(ah), ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf);
5462138570Ssam	if (bootverbose) {
5463138570Ssam		int i;
5464138570Ssam		for (i = 0; i <= WME_AC_VO; i++) {
5465138570Ssam			struct ath_txq *txq = sc->sc_ac2q[i];
5466138570Ssam			if_printf(ifp, "Use hw queue %u for %s traffic\n",
5467138570Ssam				txq->axq_qnum, ieee80211_wme_acnames[i]);
5468138570Ssam		}
5469138570Ssam		if_printf(ifp, "Use hw queue %u for CAB traffic\n",
5470138570Ssam			sc->sc_cabq->axq_qnum);
5471138570Ssam		if_printf(ifp, "Use hw queue %u for beacons\n", sc->sc_bhalq);
5472116743Ssam	}
5473155481Ssam	if (ath_rxbuf != ATH_RXBUF)
5474155481Ssam		if_printf(ifp, "using %u rx buffers\n", ath_rxbuf);
5475155481Ssam	if (ath_txbuf != ATH_TXBUF)
5476155481Ssam		if_printf(ifp, "using %u tx buffers\n", ath_txbuf);
5477203683Srpaulo	if (sc->sc_mcastkey && bootverbose)
5478203683Srpaulo		if_printf(ifp, "using multicast key search\n");
5479116743Ssam}
5480186904Ssam
5481190571Ssam#ifdef IEEE80211_SUPPORT_TDMA
5482186904Ssamstatic void
5483186904Ssamath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval)
5484186904Ssam{
5485186904Ssam	struct ath_hal *ah = sc->sc_ah;
5486186904Ssam	HAL_BEACON_TIMERS bt;
5487186904Ssam
5488186904Ssam	bt.bt_intval = bintval | HAL_BEACON_ENA;
5489186904Ssam	bt.bt_nexttbtt = nexttbtt;
5490186904Ssam	bt.bt_nextdba = (nexttbtt<<3) - sc->sc_tdmadbaprep;
5491186904Ssam	bt.bt_nextswba = (nexttbtt<<3) - sc->sc_tdmaswbaprep;
5492186904Ssam	bt.bt_nextatim = nexttbtt+1;
5493225145Sadrian	/* Enables TBTT, DBA, SWBA timers by default */
5494225145Sadrian	bt.bt_flags = 0;
5495186904Ssam	ath_hal_beaconsettimers(ah, &bt);
5496186904Ssam}
5497186904Ssam
5498186904Ssam/*
5499186904Ssam * Calculate the beacon interval.  This is periodic in the
5500186904Ssam * superframe for the bss.  We assume each station is configured
5501186904Ssam * identically wrt transmit rate so the guard time we calculate
5502186904Ssam * above will be the same on all stations.  Note we need to
5503186904Ssam * factor in the xmit time because the hardware will schedule
5504186904Ssam * a frame for transmit if the start of the frame is within
5505186904Ssam * the burst time.  When we get hardware that properly kills
5506186904Ssam * frames in the PCU we can reduce/eliminate the guard time.
5507186904Ssam *
5508186904Ssam * Roundup to 1024 is so we have 1 TU buffer in the guard time
5509186904Ssam * to deal with the granularity of the nexttbtt timer.  11n MAC's
5510186904Ssam * with 1us timer granularity should allow us to reduce/eliminate
5511186904Ssam * this.
5512186904Ssam */
5513186904Ssamstatic void
5514186904Ssamath_tdma_bintvalsetup(struct ath_softc *sc,
5515186904Ssam	const struct ieee80211_tdma_state *tdma)
5516186904Ssam{
5517186904Ssam	/* copy from vap state (XXX check all vaps have same value?) */
5518186904Ssam	sc->sc_tdmaslotlen = tdma->tdma_slotlen;
5519186904Ssam
5520186904Ssam	sc->sc_tdmabintval = roundup((sc->sc_tdmaslotlen+sc->sc_tdmaguard) *
5521186904Ssam		tdma->tdma_slotcnt, 1024);
5522186904Ssam	sc->sc_tdmabintval >>= 10;		/* TSF -> TU */
5523186904Ssam	if (sc->sc_tdmabintval & 1)
5524186904Ssam		sc->sc_tdmabintval++;
5525186904Ssam
5526186904Ssam	if (tdma->tdma_slot == 0) {
5527186904Ssam		/*
5528186904Ssam		 * Only slot 0 beacons; other slots respond.
5529186904Ssam		 */
5530186904Ssam		sc->sc_imask |= HAL_INT_SWBA;
5531186904Ssam		sc->sc_tdmaswba = 0;		/* beacon immediately */
5532186904Ssam	} else {
5533186904Ssam		/* XXX all vaps must be slot 0 or slot !0 */
5534186904Ssam		sc->sc_imask &= ~HAL_INT_SWBA;
5535186904Ssam	}
5536186904Ssam}
5537186904Ssam
5538186904Ssam/*
5539186904Ssam * Max 802.11 overhead.  This assumes no 4-address frames and
5540186904Ssam * the encapsulation done by ieee80211_encap (llc).  We also
5541186904Ssam * include potential crypto overhead.
5542186904Ssam */
5543186904Ssam#define	IEEE80211_MAXOVERHEAD \
5544186904Ssam	(sizeof(struct ieee80211_qosframe) \
5545186904Ssam	 + sizeof(struct llc) \
5546186904Ssam	 + IEEE80211_ADDR_LEN \
5547186904Ssam	 + IEEE80211_WEP_IVLEN \
5548186904Ssam	 + IEEE80211_WEP_KIDLEN \
5549186904Ssam	 + IEEE80211_WEP_CRCLEN \
5550186904Ssam	 + IEEE80211_WEP_MICLEN \
5551186904Ssam	 + IEEE80211_CRC_LEN)
5552186904Ssam
5553186904Ssam/*
5554186904Ssam * Setup initially for tdma operation.  Start the beacon
5555186904Ssam * timers and enable SWBA if we are slot 0.  Otherwise
5556186904Ssam * we wait for slot 0 to arrive so we can sync up before
5557186904Ssam * starting to transmit.
5558186904Ssam */
5559186904Ssamstatic void
5560186904Ssamath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap)
5561186904Ssam{
5562186904Ssam	struct ath_hal *ah = sc->sc_ah;
5563186904Ssam	struct ifnet *ifp = sc->sc_ifp;
5564186904Ssam	struct ieee80211com *ic = ifp->if_l2com;
5565186904Ssam	const struct ieee80211_txparam *tp;
5566186904Ssam	const struct ieee80211_tdma_state *tdma = NULL;
5567186904Ssam	int rix;
5568186904Ssam
5569186904Ssam	if (vap == NULL) {
5570186904Ssam		vap = TAILQ_FIRST(&ic->ic_vaps);   /* XXX */
5571186904Ssam		if (vap == NULL) {
5572186904Ssam			if_printf(ifp, "%s: no vaps?\n", __func__);
5573186904Ssam			return;
5574186904Ssam		}
5575186904Ssam	}
5576186904Ssam	tp = vap->iv_bss->ni_txparms;
5577186904Ssam	/*
5578186904Ssam	 * Calculate the guard time for each slot.  This is the
5579186904Ssam	 * time to send a maximal-size frame according to the
5580186904Ssam	 * fixed/lowest transmit rate.  Note that the interface
5581186904Ssam	 * mtu does not include the 802.11 overhead so we must
5582186904Ssam	 * tack that on (ath_hal_computetxtime includes the
5583186904Ssam	 * preamble and plcp in it's calculation).
5584186904Ssam	 */
5585186904Ssam	tdma = vap->iv_tdma;
5586186904Ssam	if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
5587191866Ssam		rix = ath_tx_findrix(sc, tp->ucastrate);
5588186904Ssam	else
5589191866Ssam		rix = ath_tx_findrix(sc, tp->mcastrate);
5590186904Ssam	/* XXX short preamble assumed */
5591186904Ssam	sc->sc_tdmaguard = ath_hal_computetxtime(ah, sc->sc_currates,
5592186904Ssam		ifp->if_mtu + IEEE80211_MAXOVERHEAD, rix, AH_TRUE);
5593186904Ssam
5594186904Ssam	ath_hal_intrset(ah, 0);
5595186904Ssam
5596186904Ssam	ath_beaconq_config(sc);			/* setup h/w beacon q */
5597189380Ssam	if (sc->sc_setcca)
5598189380Ssam		ath_hal_setcca(ah, AH_FALSE);	/* disable CCA */
5599186904Ssam	ath_tdma_bintvalsetup(sc, tdma);	/* calculate beacon interval */
5600186904Ssam	ath_tdma_settimers(sc, sc->sc_tdmabintval,
5601186904Ssam		sc->sc_tdmabintval | HAL_BEACON_RESET_TSF);
5602186904Ssam	sc->sc_syncbeacon = 0;
5603186904Ssam
5604186904Ssam	sc->sc_avgtsfdeltap = TDMA_DUMMY_MARKER;
5605186904Ssam	sc->sc_avgtsfdeltam = TDMA_DUMMY_MARKER;
5606186904Ssam
5607186904Ssam	ath_hal_intrset(ah, sc->sc_imask);
5608186904Ssam
5609186904Ssam	DPRINTF(sc, ATH_DEBUG_TDMA, "%s: slot %u len %uus cnt %u "
5610186904Ssam	    "bsched %u guard %uus bintval %u TU dba prep %u\n", __func__,
5611186904Ssam	    tdma->tdma_slot, tdma->tdma_slotlen, tdma->tdma_slotcnt,
5612186904Ssam	    tdma->tdma_bintval, sc->sc_tdmaguard, sc->sc_tdmabintval,
5613186904Ssam	    sc->sc_tdmadbaprep);
5614186904Ssam}
5615186904Ssam
5616186904Ssam/*
5617186904Ssam * Update tdma operation.  Called from the 802.11 layer
5618186904Ssam * when a beacon is received from the TDMA station operating
5619186904Ssam * in the slot immediately preceding us in the bss.  Use
5620186904Ssam * the rx timestamp for the beacon frame to update our
5621186904Ssam * beacon timers so we follow their schedule.  Note that
5622186904Ssam * by using the rx timestamp we implicitly include the
5623186904Ssam * propagation delay in our schedule.
5624186904Ssam */
5625186904Ssamstatic void
5626186904Ssamath_tdma_update(struct ieee80211_node *ni,
5627189980Ssam	const struct ieee80211_tdma_param *tdma, int changed)
5628186904Ssam{
5629186904Ssam#define	TSF_TO_TU(_h,_l) \
5630186904Ssam	((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
5631186904Ssam#define	TU_TO_TSF(_tu)	(((u_int64_t)(_tu)) << 10)
5632186904Ssam	struct ieee80211vap *vap = ni->ni_vap;
5633186904Ssam	struct ieee80211com *ic = ni->ni_ic;
5634186904Ssam	struct ath_softc *sc = ic->ic_ifp->if_softc;
5635186904Ssam	struct ath_hal *ah = sc->sc_ah;
5636186904Ssam	const HAL_RATE_TABLE *rt = sc->sc_currates;
5637225444Sadrian	u_int64_t tsf, rstamp, nextslot, nexttbtt;
5638225444Sadrian	u_int32_t txtime, nextslottu;
5639186904Ssam	int32_t tudelta, tsfdelta;
5640186904Ssam	const struct ath_rx_status *rs;
5641186904Ssam	int rix;
5642186904Ssam
5643186904Ssam	sc->sc_stats.ast_tdma_update++;
5644186904Ssam
5645186904Ssam	/*
5646186904Ssam	 * Check for and adopt configuration changes.
5647186904Ssam	 */
5648189980Ssam	if (changed != 0) {
5649186904Ssam		const struct ieee80211_tdma_state *ts = vap->iv_tdma;
5650186904Ssam
5651186904Ssam		ath_tdma_bintvalsetup(sc, ts);
5652191020Ssam		if (changed & TDMA_UPDATE_SLOTLEN)
5653191020Ssam			ath_wme_update(ic);
5654186904Ssam
5655186904Ssam		DPRINTF(sc, ATH_DEBUG_TDMA,
5656186904Ssam		    "%s: adopt slot %u slotcnt %u slotlen %u us "
5657186904Ssam		    "bintval %u TU\n", __func__,
5658186904Ssam		    ts->tdma_slot, ts->tdma_slotcnt, ts->tdma_slotlen,
5659186904Ssam		    sc->sc_tdmabintval);
5660186904Ssam
5661186904Ssam		/* XXX right? */
5662186904Ssam		ath_hal_intrset(ah, sc->sc_imask);
5663186904Ssam		/* NB: beacon timers programmed below */
5664186904Ssam	}
5665186904Ssam
5666186904Ssam	/* extend rx timestamp to 64 bits */
5667192468Ssam	rs = sc->sc_lastrs;
5668186904Ssam	tsf = ath_hal_gettsf64(ah);
5669225444Sadrian	rstamp = ath_extend_tsf(sc, rs->rs_tstamp, tsf);
5670186904Ssam	/*
5671186904Ssam	 * The rx timestamp is set by the hardware on completing
5672186904Ssam	 * reception (at the point where the rx descriptor is DMA'd
5673186904Ssam	 * to the host).  To find the start of our next slot we
5674186904Ssam	 * must adjust this time by the time required to send
5675186904Ssam	 * the packet just received.
5676186904Ssam	 */
5677186904Ssam	rix = rt->rateCodeToIndex[rs->rs_rate];
5678186904Ssam	txtime = ath_hal_computetxtime(ah, rt, rs->rs_datalen, rix,
5679186904Ssam	    rt->info[rix].shortPreamble);
5680186904Ssam	/* NB: << 9 is to cvt to TU and /2 */
5681186904Ssam	nextslot = (rstamp - txtime) + (sc->sc_tdmabintval << 9);
5682186904Ssam	nextslottu = TSF_TO_TU(nextslot>>32, nextslot) & HAL_BEACON_PERIOD;
5683186904Ssam
5684186904Ssam	/*
5685225444Sadrian	 * Retrieve the hardware NextTBTT in usecs
5686225444Sadrian	 * and calculate the difference between what the
5687186904Ssam	 * other station thinks and what we have programmed.  This
5688186904Ssam	 * lets us figure how to adjust our timers to match.  The
5689186904Ssam	 * adjustments are done by pulling the TSF forward and possibly
5690186904Ssam	 * rewriting the beacon timers.
5691186904Ssam	 */
5692225444Sadrian	nexttbtt = ath_hal_getnexttbtt(ah);
5693225444Sadrian	tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD + 1)) - nexttbtt);
5694186904Ssam
5695186904Ssam	DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
5696186904Ssam	    "tsfdelta %d avg +%d/-%d\n", tsfdelta,
5697186904Ssam	    TDMA_AVG(sc->sc_avgtsfdeltap), TDMA_AVG(sc->sc_avgtsfdeltam));
5698186904Ssam
5699186904Ssam	if (tsfdelta < 0) {
5700186904Ssam		TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0);
5701186904Ssam		TDMA_SAMPLE(sc->sc_avgtsfdeltam, -tsfdelta);
5702186904Ssam		tsfdelta = -tsfdelta % 1024;
5703186904Ssam		nextslottu++;
5704186904Ssam	} else if (tsfdelta > 0) {
5705186904Ssam		TDMA_SAMPLE(sc->sc_avgtsfdeltap, tsfdelta);
5706186904Ssam		TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0);
5707186904Ssam		tsfdelta = 1024 - (tsfdelta % 1024);
5708186904Ssam		nextslottu++;
5709186904Ssam	} else {
5710186904Ssam		TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0);
5711186904Ssam		TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0);
5712186904Ssam	}
5713225444Sadrian	tudelta = nextslottu - TSF_TO_TU(nexttbtt >> 32, nexttbtt);
5714186904Ssam
5715186904Ssam	/*
5716186904Ssam	 * Copy sender's timetstamp into tdma ie so they can
5717186904Ssam	 * calculate roundtrip time.  We submit a beacon frame
5718186904Ssam	 * below after any timer adjustment.  The frame goes out
5719186904Ssam	 * at the next TBTT so the sender can calculate the
5720186904Ssam	 * roundtrip by inspecting the tdma ie in our beacon frame.
5721186904Ssam	 *
5722186904Ssam	 * NB: This tstamp is subtlely preserved when
5723186904Ssam	 *     IEEE80211_BEACON_TDMA is marked (e.g. when the
5724186904Ssam	 *     slot position changes) because ieee80211_add_tdma
5725186904Ssam	 *     skips over the data.
5726186904Ssam	 */
5727186904Ssam	memcpy(ATH_VAP(vap)->av_boff.bo_tdma +
5728186904Ssam		__offsetof(struct ieee80211_tdma_param, tdma_tstamp),
5729186904Ssam		&ni->ni_tstamp.data, 8);
5730186904Ssam#if 0
5731186904Ssam	DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
5732225444Sadrian	    "tsf %llu nextslot %llu (%d, %d) nextslottu %u nexttbtt %llu (%d)\n",
5733186904Ssam	    (unsigned long long) tsf, (unsigned long long) nextslot,
5734225444Sadrian	    (int)(nextslot - tsf), tsfdelta, nextslottu, nexttbtt, tudelta);
5735186904Ssam#endif
5736186904Ssam	/*
5737186904Ssam	 * Adjust the beacon timers only when pulling them forward
5738186904Ssam	 * or when going back by less than the beacon interval.
5739186904Ssam	 * Negative jumps larger than the beacon interval seem to
5740186904Ssam	 * cause the timers to stop and generally cause instability.
5741186904Ssam	 * This basically filters out jumps due to missed beacons.
5742186904Ssam	 */
5743186904Ssam	if (tudelta != 0 && (tudelta > 0 || -tudelta < sc->sc_tdmabintval)) {
5744186904Ssam		ath_tdma_settimers(sc, nextslottu, sc->sc_tdmabintval);
5745186904Ssam		sc->sc_stats.ast_tdma_timers++;
5746186904Ssam	}
5747186904Ssam	if (tsfdelta > 0) {
5748186904Ssam		ath_hal_adjusttsf(ah, tsfdelta);
5749186904Ssam		sc->sc_stats.ast_tdma_tsf++;
5750186904Ssam	}
5751186904Ssam	ath_tdma_beacon_send(sc, vap);		/* prepare response */
5752186904Ssam#undef TU_TO_TSF
5753186904Ssam#undef TSF_TO_TU
5754186904Ssam}
5755186904Ssam
5756186904Ssam/*
5757186904Ssam * Transmit a beacon frame at SWBA.  Dynamic updates
5758186904Ssam * to the frame contents are done as needed.
5759186904Ssam */
5760186904Ssamstatic void
5761186904Ssamath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap)
5762186904Ssam{
5763186904Ssam	struct ath_hal *ah = sc->sc_ah;
5764186904Ssam	struct ath_buf *bf;
5765186904Ssam	int otherant;
5766186904Ssam
5767186904Ssam	/*
5768186904Ssam	 * Check if the previous beacon has gone out.  If
5769186904Ssam	 * not don't try to post another, skip this period
5770186904Ssam	 * and wait for the next.  Missed beacons indicate
5771186904Ssam	 * a problem and should not occur.  If we miss too
5772186904Ssam	 * many consecutive beacons reset the device.
5773186904Ssam	 */
5774186904Ssam	if (ath_hal_numtxpending(ah, sc->sc_bhalq) != 0) {
5775186904Ssam		sc->sc_bmisscount++;
5776186904Ssam		DPRINTF(sc, ATH_DEBUG_BEACON,
5777186904Ssam			"%s: missed %u consecutive beacons\n",
5778186904Ssam			__func__, sc->sc_bmisscount);
5779188446Ssam		if (sc->sc_bmisscount >= ath_bstuck_threshold)
5780186904Ssam			taskqueue_enqueue(sc->sc_tq, &sc->sc_bstucktask);
5781186904Ssam		return;
5782186904Ssam	}
5783186904Ssam	if (sc->sc_bmisscount != 0) {
5784186904Ssam		DPRINTF(sc, ATH_DEBUG_BEACON,
5785186904Ssam			"%s: resume beacon xmit after %u misses\n",
5786186904Ssam			__func__, sc->sc_bmisscount);
5787186904Ssam		sc->sc_bmisscount = 0;
5788186904Ssam	}
5789186904Ssam
5790186904Ssam	/*
5791186904Ssam	 * Check recent per-antenna transmit statistics and flip
5792186904Ssam	 * the default antenna if noticeably more frames went out
5793186904Ssam	 * on the non-default antenna.
5794186904Ssam	 * XXX assumes 2 anntenae
5795186904Ssam	 */
5796186904Ssam	if (!sc->sc_diversity) {
5797186904Ssam		otherant = sc->sc_defant & 1 ? 2 : 1;
5798186904Ssam		if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] + 2)
5799186904Ssam			ath_setdefantenna(sc, otherant);
5800186904Ssam		sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0;
5801186904Ssam	}
5802186904Ssam
5803186904Ssam	bf = ath_beacon_generate(sc, vap);
5804186904Ssam	if (bf != NULL) {
5805186904Ssam		/*
5806186904Ssam		 * Stop any current dma and put the new frame on the queue.
5807186904Ssam		 * This should never fail since we check above that no frames
5808186904Ssam		 * are still pending on the queue.
5809186904Ssam		 */
5810186904Ssam		if (!ath_hal_stoptxdma(ah, sc->sc_bhalq)) {
5811186904Ssam			DPRINTF(sc, ATH_DEBUG_ANY,
5812186904Ssam				"%s: beacon queue %u did not stop?\n",
5813186904Ssam				__func__, sc->sc_bhalq);
5814186904Ssam			/* NB: the HAL still stops DMA, so proceed */
5815186904Ssam		}
5816186904Ssam		ath_hal_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr);
5817186904Ssam		ath_hal_txstart(ah, sc->sc_bhalq);
5818186904Ssam
5819186904Ssam		sc->sc_stats.ast_be_xmit++;		/* XXX per-vap? */
5820186904Ssam
5821186904Ssam		/*
5822186904Ssam		 * Record local TSF for our last send for use
5823186904Ssam		 * in arbitrating slot collisions.
5824186904Ssam		 */
5825186904Ssam		vap->iv_bss->ni_tstamp.tsf = ath_hal_gettsf64(ah);
5826186904Ssam	}
5827186904Ssam}
5828190571Ssam#endif /* IEEE80211_SUPPORT_TDMA */
5829211303Sadrian
5830222585Sadrianstatic void
5831222585Sadrianath_dfs_tasklet(void *p, int npending)
5832222585Sadrian{
5833222585Sadrian	struct ath_softc *sc = (struct ath_softc *) p;
5834222585Sadrian	struct ifnet *ifp = sc->sc_ifp;
5835222585Sadrian	struct ieee80211com *ic = ifp->if_l2com;
5836222585Sadrian
5837222585Sadrian	/*
5838222585Sadrian	 * If previous processing has found a radar event,
5839222585Sadrian	 * signal this to the net80211 layer to begin DFS
5840222585Sadrian	 * processing.
5841222585Sadrian	 */
5842222585Sadrian	if (ath_dfs_process_radar_event(sc, sc->sc_curchan)) {
5843222585Sadrian		/* DFS event found, initiate channel change */
5844222585Sadrian		ieee80211_dfs_notify_radar(ic, sc->sc_curchan);
5845222585Sadrian	}
5846222585Sadrian}
5847222585Sadrian
5848220185SadrianMODULE_VERSION(if_ath, 1);
5849220185SadrianMODULE_DEPEND(if_ath, wlan, 1, 1, 1);          /* 802.11 media layer */
5850