1219180Sadrian/*-
2219180Sadrian * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3219180Sadrian * All rights reserved.
4219180Sadrian *
5219180Sadrian * Redistribution and use in source and binary forms, with or without
6219180Sadrian * modification, are permitted provided that the following conditions
7219180Sadrian * are met:
8219180Sadrian * 1. Redistributions of source code must retain the above copyright
9219180Sadrian *    notice, this list of conditions and the following disclaimer,
10219180Sadrian *    without modification.
11219180Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12219180Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13219180Sadrian *    redistribution must be conditioned upon including a substantially
14219180Sadrian *    similar Disclaimer requirement for further binary redistribution.
15219180Sadrian *
16219180Sadrian * NO WARRANTY
17219180Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18219180Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19219180Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20219180Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21219180Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22219180Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23219180Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24219180Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25219180Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26219180Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27219180Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28219180Sadrian */
29219180Sadrian
30219180Sadrian#include <sys/cdefs.h>
31219180Sadrian__FBSDID("$FreeBSD$");
32219180Sadrian
33219180Sadrian/*
34219180Sadrian * Driver for the Atheros Wireless LAN controller.
35219180Sadrian *
36219180Sadrian * This software is derived from work of Atsushi Onoe; his contribution
37219180Sadrian * is greatly appreciated.
38219180Sadrian */
39219180Sadrian
40219180Sadrian#include "opt_inet.h"
41219180Sadrian#include "opt_ath.h"
42219180Sadrian#include "opt_wlan.h"
43219180Sadrian
44219180Sadrian#include <sys/param.h>
45219180Sadrian#include <sys/systm.h>
46219180Sadrian#include <sys/sysctl.h>
47219180Sadrian#include <sys/mbuf.h>
48219180Sadrian#include <sys/malloc.h>
49219180Sadrian#include <sys/lock.h>
50219180Sadrian#include <sys/mutex.h>
51219180Sadrian#include <sys/kernel.h>
52219180Sadrian#include <sys/socket.h>
53219180Sadrian#include <sys/sockio.h>
54219180Sadrian#include <sys/errno.h>
55219180Sadrian#include <sys/callout.h>
56219180Sadrian#include <sys/bus.h>
57219180Sadrian#include <sys/endian.h>
58219180Sadrian#include <sys/kthread.h>
59219180Sadrian#include <sys/taskqueue.h>
60219180Sadrian#include <sys/priv.h>
61219180Sadrian
62219180Sadrian#include <machine/bus.h>
63219180Sadrian
64219180Sadrian#include <net/if.h>
65219180Sadrian#include <net/if_dl.h>
66219180Sadrian#include <net/if_media.h>
67219180Sadrian#include <net/if_types.h>
68219180Sadrian#include <net/if_arp.h>
69219180Sadrian#include <net/ethernet.h>
70219180Sadrian#include <net/if_llc.h>
71219180Sadrian
72219180Sadrian#include <net80211/ieee80211_var.h>
73219180Sadrian#include <net80211/ieee80211_regdomain.h>
74219180Sadrian#ifdef IEEE80211_SUPPORT_SUPERG
75219180Sadrian#include <net80211/ieee80211_superg.h>
76219180Sadrian#endif
77219180Sadrian#ifdef IEEE80211_SUPPORT_TDMA
78219180Sadrian#include <net80211/ieee80211_tdma.h>
79219180Sadrian#endif
80219180Sadrian
81219180Sadrian#include <net/bpf.h>
82219180Sadrian
83219180Sadrian#ifdef INET
84219180Sadrian#include <netinet/in.h>
85219180Sadrian#include <netinet/if_ether.h>
86219180Sadrian#endif
87219180Sadrian
88219180Sadrian#include <dev/ath/if_athvar.h>
89219180Sadrian#include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
90219180Sadrian#include <dev/ath/ath_hal/ah_diagcodes.h>
91219180Sadrian
92219180Sadrian#include <dev/ath/if_ath_debug.h>
93219180Sadrian#include <dev/ath/if_ath_misc.h>
94219180Sadrian#include <dev/ath/if_ath_tx.h>
95219180Sadrian#include <dev/ath/if_ath_sysctl.h>
96219180Sadrian
97219180Sadrian#ifdef ATH_TX99_DIAG
98219180Sadrian#include <dev/ath/ath_tx99/ath_tx99.h>
99219180Sadrian#endif
100219180Sadrian
101219180Sadrianstatic int
102219180Sadrianath_sysctl_slottime(SYSCTL_HANDLER_ARGS)
103219180Sadrian{
104219180Sadrian	struct ath_softc *sc = arg1;
105219180Sadrian	u_int slottime = ath_hal_getslottime(sc->sc_ah);
106219180Sadrian	int error;
107219180Sadrian
108219180Sadrian	error = sysctl_handle_int(oidp, &slottime, 0, req);
109219180Sadrian	if (error || !req->newptr)
110219180Sadrian		return error;
111219180Sadrian	return !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0;
112219180Sadrian}
113219180Sadrian
114219180Sadrianstatic int
115219180Sadrianath_sysctl_acktimeout(SYSCTL_HANDLER_ARGS)
116219180Sadrian{
117219180Sadrian	struct ath_softc *sc = arg1;
118219180Sadrian	u_int acktimeout = ath_hal_getacktimeout(sc->sc_ah);
119219180Sadrian	int error;
120219180Sadrian
121219180Sadrian	error = sysctl_handle_int(oidp, &acktimeout, 0, req);
122219180Sadrian	if (error || !req->newptr)
123219180Sadrian		return error;
124219180Sadrian	return !ath_hal_setacktimeout(sc->sc_ah, acktimeout) ? EINVAL : 0;
125219180Sadrian}
126219180Sadrian
127219180Sadrianstatic int
128219180Sadrianath_sysctl_ctstimeout(SYSCTL_HANDLER_ARGS)
129219180Sadrian{
130219180Sadrian	struct ath_softc *sc = arg1;
131219180Sadrian	u_int ctstimeout = ath_hal_getctstimeout(sc->sc_ah);
132219180Sadrian	int error;
133219180Sadrian
134219180Sadrian	error = sysctl_handle_int(oidp, &ctstimeout, 0, req);
135219180Sadrian	if (error || !req->newptr)
136219180Sadrian		return error;
137219180Sadrian	return !ath_hal_setctstimeout(sc->sc_ah, ctstimeout) ? EINVAL : 0;
138219180Sadrian}
139219180Sadrian
140219180Sadrianstatic int
141219180Sadrianath_sysctl_softled(SYSCTL_HANDLER_ARGS)
142219180Sadrian{
143219180Sadrian	struct ath_softc *sc = arg1;
144219180Sadrian	int softled = sc->sc_softled;
145219180Sadrian	int error;
146219180Sadrian
147219180Sadrian	error = sysctl_handle_int(oidp, &softled, 0, req);
148219180Sadrian	if (error || !req->newptr)
149219180Sadrian		return error;
150219180Sadrian	softled = (softled != 0);
151219180Sadrian	if (softled != sc->sc_softled) {
152219180Sadrian		if (softled) {
153219180Sadrian			/* NB: handle any sc_ledpin change */
154219180Sadrian			ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin,
155219180Sadrian			    HAL_GPIO_MUX_MAC_NETWORK_LED);
156219180Sadrian			ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin,
157219180Sadrian				!sc->sc_ledon);
158219180Sadrian		}
159219180Sadrian		sc->sc_softled = softled;
160219180Sadrian	}
161219180Sadrian	return 0;
162219180Sadrian}
163219180Sadrian
164219180Sadrianstatic int
165219180Sadrianath_sysctl_ledpin(SYSCTL_HANDLER_ARGS)
166219180Sadrian{
167219180Sadrian	struct ath_softc *sc = arg1;
168219180Sadrian	int ledpin = sc->sc_ledpin;
169219180Sadrian	int error;
170219180Sadrian
171219180Sadrian	error = sysctl_handle_int(oidp, &ledpin, 0, req);
172219180Sadrian	if (error || !req->newptr)
173219180Sadrian		return error;
174219180Sadrian	if (ledpin != sc->sc_ledpin) {
175219180Sadrian		sc->sc_ledpin = ledpin;
176219180Sadrian		if (sc->sc_softled) {
177219180Sadrian			ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin,
178219180Sadrian			    HAL_GPIO_MUX_MAC_NETWORK_LED);
179219180Sadrian			ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin,
180219180Sadrian				!sc->sc_ledon);
181219180Sadrian		}
182219180Sadrian	}
183219180Sadrian	return 0;
184219180Sadrian}
185219180Sadrian
186219180Sadrianstatic int
187219180Sadrianath_sysctl_txantenna(SYSCTL_HANDLER_ARGS)
188219180Sadrian{
189219180Sadrian	struct ath_softc *sc = arg1;
190219180Sadrian	u_int txantenna = ath_hal_getantennaswitch(sc->sc_ah);
191219180Sadrian	int error;
192219180Sadrian
193219180Sadrian	error = sysctl_handle_int(oidp, &txantenna, 0, req);
194219180Sadrian	if (!error && req->newptr) {
195219180Sadrian		/* XXX assumes 2 antenna ports */
196219180Sadrian		if (txantenna < HAL_ANT_VARIABLE || txantenna > HAL_ANT_FIXED_B)
197219180Sadrian			return EINVAL;
198219180Sadrian		ath_hal_setantennaswitch(sc->sc_ah, txantenna);
199219180Sadrian		/*
200219180Sadrian		 * NB: with the switch locked this isn't meaningful,
201219180Sadrian		 *     but set it anyway so things like radiotap get
202219180Sadrian		 *     consistent info in their data.
203219180Sadrian		 */
204219180Sadrian		sc->sc_txantenna = txantenna;
205219180Sadrian	}
206219180Sadrian	return error;
207219180Sadrian}
208219180Sadrian
209219180Sadrianstatic int
210219180Sadrianath_sysctl_rxantenna(SYSCTL_HANDLER_ARGS)
211219180Sadrian{
212219180Sadrian	struct ath_softc *sc = arg1;
213219180Sadrian	u_int defantenna = ath_hal_getdefantenna(sc->sc_ah);
214219180Sadrian	int error;
215219180Sadrian
216219180Sadrian	error = sysctl_handle_int(oidp, &defantenna, 0, req);
217219180Sadrian	if (!error && req->newptr)
218219180Sadrian		ath_hal_setdefantenna(sc->sc_ah, defantenna);
219219180Sadrian	return error;
220219180Sadrian}
221219180Sadrian
222219180Sadrianstatic int
223219180Sadrianath_sysctl_diversity(SYSCTL_HANDLER_ARGS)
224219180Sadrian{
225219180Sadrian	struct ath_softc *sc = arg1;
226219180Sadrian	u_int diversity = ath_hal_getdiversity(sc->sc_ah);
227219180Sadrian	int error;
228219180Sadrian
229219180Sadrian	error = sysctl_handle_int(oidp, &diversity, 0, req);
230219180Sadrian	if (error || !req->newptr)
231219180Sadrian		return error;
232219180Sadrian	if (!ath_hal_setdiversity(sc->sc_ah, diversity))
233219180Sadrian		return EINVAL;
234219180Sadrian	sc->sc_diversity = diversity;
235219180Sadrian	return 0;
236219180Sadrian}
237219180Sadrian
238219180Sadrianstatic int
239219180Sadrianath_sysctl_diag(SYSCTL_HANDLER_ARGS)
240219180Sadrian{
241219180Sadrian	struct ath_softc *sc = arg1;
242219180Sadrian	u_int32_t diag;
243219180Sadrian	int error;
244219180Sadrian
245219180Sadrian	if (!ath_hal_getdiag(sc->sc_ah, &diag))
246219180Sadrian		return EINVAL;
247219180Sadrian	error = sysctl_handle_int(oidp, &diag, 0, req);
248219180Sadrian	if (error || !req->newptr)
249219180Sadrian		return error;
250219180Sadrian	return !ath_hal_setdiag(sc->sc_ah, diag) ? EINVAL : 0;
251219180Sadrian}
252219180Sadrian
253219180Sadrianstatic int
254219180Sadrianath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
255219180Sadrian{
256219180Sadrian	struct ath_softc *sc = arg1;
257219180Sadrian	struct ifnet *ifp = sc->sc_ifp;
258219180Sadrian	u_int32_t scale;
259219180Sadrian	int error;
260219180Sadrian
261219180Sadrian	(void) ath_hal_gettpscale(sc->sc_ah, &scale);
262219180Sadrian	error = sysctl_handle_int(oidp, &scale, 0, req);
263219180Sadrian	if (error || !req->newptr)
264219180Sadrian		return error;
265219180Sadrian	return !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL :
266219180Sadrian	    (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp) : 0;
267219180Sadrian}
268219180Sadrian
269219180Sadrianstatic int
270219180Sadrianath_sysctl_tpc(SYSCTL_HANDLER_ARGS)
271219180Sadrian{
272219180Sadrian	struct ath_softc *sc = arg1;
273219180Sadrian	u_int tpc = ath_hal_gettpc(sc->sc_ah);
274219180Sadrian	int error;
275219180Sadrian
276219180Sadrian	error = sysctl_handle_int(oidp, &tpc, 0, req);
277219180Sadrian	if (error || !req->newptr)
278219180Sadrian		return error;
279219180Sadrian	return !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0;
280219180Sadrian}
281219180Sadrian
282219180Sadrianstatic int
283219180Sadrianath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
284219180Sadrian{
285219180Sadrian	struct ath_softc *sc = arg1;
286219180Sadrian	struct ifnet *ifp = sc->sc_ifp;
287219180Sadrian	struct ath_hal *ah = sc->sc_ah;
288219180Sadrian	u_int rfkill = ath_hal_getrfkill(ah);
289219180Sadrian	int error;
290219180Sadrian
291219180Sadrian	error = sysctl_handle_int(oidp, &rfkill, 0, req);
292219180Sadrian	if (error || !req->newptr)
293219180Sadrian		return error;
294219180Sadrian	if (rfkill == ath_hal_getrfkill(ah))	/* unchanged */
295219180Sadrian		return 0;
296219180Sadrian	if (!ath_hal_setrfkill(ah, rfkill))
297219180Sadrian		return EINVAL;
298219180Sadrian	return (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp) : 0;
299219180Sadrian}
300219180Sadrian
301219180Sadrianstatic int
302219180Sadrianath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS)
303219180Sadrian{
304219180Sadrian	struct ath_softc *sc = arg1;
305219180Sadrian	u_int rfsilent;
306219180Sadrian	int error;
307219180Sadrian
308219180Sadrian	(void) ath_hal_getrfsilent(sc->sc_ah, &rfsilent);
309219180Sadrian	error = sysctl_handle_int(oidp, &rfsilent, 0, req);
310219180Sadrian	if (error || !req->newptr)
311219180Sadrian		return error;
312219180Sadrian	if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent))
313219180Sadrian		return EINVAL;
314219180Sadrian	sc->sc_rfsilentpin = rfsilent & 0x1c;
315219180Sadrian	sc->sc_rfsilentpol = (rfsilent & 0x2) != 0;
316219180Sadrian	return 0;
317219180Sadrian}
318219180Sadrian
319219180Sadrianstatic int
320219180Sadrianath_sysctl_tpack(SYSCTL_HANDLER_ARGS)
321219180Sadrian{
322219180Sadrian	struct ath_softc *sc = arg1;
323219180Sadrian	u_int32_t tpack;
324219180Sadrian	int error;
325219180Sadrian
326219180Sadrian	(void) ath_hal_gettpack(sc->sc_ah, &tpack);
327219180Sadrian	error = sysctl_handle_int(oidp, &tpack, 0, req);
328219180Sadrian	if (error || !req->newptr)
329219180Sadrian		return error;
330219180Sadrian	return !ath_hal_settpack(sc->sc_ah, tpack) ? EINVAL : 0;
331219180Sadrian}
332219180Sadrian
333219180Sadrianstatic int
334219180Sadrianath_sysctl_tpcts(SYSCTL_HANDLER_ARGS)
335219180Sadrian{
336219180Sadrian	struct ath_softc *sc = arg1;
337219180Sadrian	u_int32_t tpcts;
338219180Sadrian	int error;
339219180Sadrian
340219180Sadrian	(void) ath_hal_gettpcts(sc->sc_ah, &tpcts);
341219180Sadrian	error = sysctl_handle_int(oidp, &tpcts, 0, req);
342219180Sadrian	if (error || !req->newptr)
343219180Sadrian		return error;
344219180Sadrian	return !ath_hal_settpcts(sc->sc_ah, tpcts) ? EINVAL : 0;
345219180Sadrian}
346219180Sadrian
347219180Sadrianstatic int
348219180Sadrianath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
349219180Sadrian{
350219180Sadrian	struct ath_softc *sc = arg1;
351219180Sadrian	int intmit, error;
352219180Sadrian
353219180Sadrian	intmit = ath_hal_getintmit(sc->sc_ah);
354219180Sadrian	error = sysctl_handle_int(oidp, &intmit, 0, req);
355219180Sadrian	if (error || !req->newptr)
356219180Sadrian		return error;
357224502Sadrian
358224502Sadrian	/* reusing error; 1 here means "good"; 0 means "fail" */
359224502Sadrian	error = ath_hal_setintmit(sc->sc_ah, intmit);
360224502Sadrian	if (! error)
361224502Sadrian		return EINVAL;
362224502Sadrian
363224502Sadrian	/*
364224502Sadrian	 * Reset the hardware here - disabling ANI in the HAL
365224502Sadrian	 * doesn't reset ANI related registers, so it'll leave
366224502Sadrian	 * things in an inconsistent state.
367224502Sadrian	 */
368224502Sadrian	if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
369224502Sadrian		ath_reset(sc->sc_ifp);
370224502Sadrian
371224502Sadrian	return 0;
372219180Sadrian}
373219180Sadrian
374219180Sadrian#ifdef IEEE80211_SUPPORT_TDMA
375219180Sadrianstatic int
376219180Sadrianath_sysctl_setcca(SYSCTL_HANDLER_ARGS)
377219180Sadrian{
378219180Sadrian	struct ath_softc *sc = arg1;
379219180Sadrian	int setcca, error;
380219180Sadrian
381219180Sadrian	setcca = sc->sc_setcca;
382219180Sadrian	error = sysctl_handle_int(oidp, &setcca, 0, req);
383219180Sadrian	if (error || !req->newptr)
384219180Sadrian		return error;
385219180Sadrian	sc->sc_setcca = (setcca != 0);
386219180Sadrian	return 0;
387219180Sadrian}
388219180Sadrian#endif /* IEEE80211_SUPPORT_TDMA */
389219180Sadrian
390219180Sadrianvoid
391219180Sadrianath_sysctlattach(struct ath_softc *sc)
392219180Sadrian{
393219180Sadrian	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
394219180Sadrian	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
395219180Sadrian	struct ath_hal *ah = sc->sc_ah;
396219180Sadrian
397219180Sadrian	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
398219180Sadrian		"countrycode", CTLFLAG_RD, &sc->sc_eecc, 0,
399219180Sadrian		"EEPROM country code");
400219180Sadrian	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
401219180Sadrian		"regdomain", CTLFLAG_RD, &sc->sc_eerd, 0,
402219180Sadrian		"EEPROM regdomain code");
403219180Sadrian#ifdef	ATH_DEBUG
404219180Sadrian	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
405219180Sadrian		"debug", CTLFLAG_RW, &sc->sc_debug, 0,
406219180Sadrian		"control debugging printfs");
407219180Sadrian#endif
408219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
409219180Sadrian		"slottime", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
410219180Sadrian		ath_sysctl_slottime, "I", "802.11 slot time (us)");
411219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
412219180Sadrian		"acktimeout", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
413219180Sadrian		ath_sysctl_acktimeout, "I", "802.11 ACK timeout (us)");
414219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
415219180Sadrian		"ctstimeout", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
416219180Sadrian		ath_sysctl_ctstimeout, "I", "802.11 CTS timeout (us)");
417219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
418219180Sadrian		"softled", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
419219180Sadrian		ath_sysctl_softled, "I", "enable/disable software LED support");
420219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
421219180Sadrian		"ledpin", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
422219180Sadrian		ath_sysctl_ledpin, "I", "GPIO pin connected to LED");
423219180Sadrian	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
424219180Sadrian		"ledon", CTLFLAG_RW, &sc->sc_ledon, 0,
425219180Sadrian		"setting to turn LED on");
426219180Sadrian	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
427219180Sadrian		"ledidle", CTLFLAG_RW, &sc->sc_ledidle, 0,
428219180Sadrian		"idle time for inactivity LED (ticks)");
429219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
430219180Sadrian		"txantenna", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
431219180Sadrian		ath_sysctl_txantenna, "I", "antenna switch");
432219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
433219180Sadrian		"rxantenna", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
434219180Sadrian		ath_sysctl_rxantenna, "I", "default/rx antenna");
435219180Sadrian	if (ath_hal_hasdiversity(ah))
436219180Sadrian		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
437219180Sadrian			"diversity", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
438219180Sadrian			ath_sysctl_diversity, "I", "antenna diversity");
439219180Sadrian	sc->sc_txintrperiod = ATH_TXINTR_PERIOD;
440219180Sadrian	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
441219180Sadrian		"txintrperiod", CTLFLAG_RW, &sc->sc_txintrperiod, 0,
442219180Sadrian		"tx descriptor batching");
443219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
444219180Sadrian		"diag", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
445219180Sadrian		ath_sysctl_diag, "I", "h/w diagnostic control");
446219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
447219180Sadrian		"tpscale", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
448219180Sadrian		ath_sysctl_tpscale, "I", "tx power scaling");
449219180Sadrian	if (ath_hal_hastpc(ah)) {
450219180Sadrian		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
451219180Sadrian			"tpc", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
452219180Sadrian			ath_sysctl_tpc, "I", "enable/disable per-packet TPC");
453219180Sadrian		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
454219180Sadrian			"tpack", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
455219180Sadrian			ath_sysctl_tpack, "I", "tx power for ack frames");
456219180Sadrian		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
457219180Sadrian			"tpcts", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
458219180Sadrian			ath_sysctl_tpcts, "I", "tx power for cts frames");
459219180Sadrian	}
460219180Sadrian	if (ath_hal_hasrfsilent(ah)) {
461219180Sadrian		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
462219180Sadrian			"rfsilent", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
463219180Sadrian			ath_sysctl_rfsilent, "I", "h/w RF silent config");
464219180Sadrian		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
465219180Sadrian			"rfkill", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
466219180Sadrian			ath_sysctl_rfkill, "I", "enable/disable RF kill switch");
467219180Sadrian	}
468219180Sadrian	if (ath_hal_hasintmit(ah)) {
469219180Sadrian		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
470219180Sadrian			"intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
471219180Sadrian			ath_sysctl_intmit, "I", "interference mitigation");
472219180Sadrian	}
473219180Sadrian	sc->sc_monpass = HAL_RXERR_DECRYPT | HAL_RXERR_MIC;
474219180Sadrian	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
475219180Sadrian		"monpass", CTLFLAG_RW, &sc->sc_monpass, 0,
476219180Sadrian		"mask of error frames to pass when monitoring");
477219180Sadrian#ifdef IEEE80211_SUPPORT_TDMA
478219180Sadrian	if (ath_hal_macversion(ah) > 0x78) {
479219180Sadrian		sc->sc_tdmadbaprep = 2;
480219180Sadrian		SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
481219180Sadrian			"dbaprep", CTLFLAG_RW, &sc->sc_tdmadbaprep, 0,
482219180Sadrian			"TDMA DBA preparation time");
483219180Sadrian		sc->sc_tdmaswbaprep = 10;
484219180Sadrian		SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
485219180Sadrian			"swbaprep", CTLFLAG_RW, &sc->sc_tdmaswbaprep, 0,
486219180Sadrian			"TDMA SWBA preparation time");
487219180Sadrian		SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
488219180Sadrian			"guardtime", CTLFLAG_RW, &sc->sc_tdmaguard, 0,
489219180Sadrian			"TDMA slot guard time");
490219180Sadrian		SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
491219180Sadrian			"superframe", CTLFLAG_RD, &sc->sc_tdmabintval, 0,
492219180Sadrian			"TDMA calculated super frame");
493219180Sadrian		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
494219180Sadrian			"setcca", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
495219180Sadrian			ath_sysctl_setcca, "I", "enable CCA control");
496219180Sadrian	}
497219180Sadrian#endif
498219180Sadrian}
499219180Sadrian
500219180Sadrianstatic int
501219180Sadrianath_sysctl_clearstats(SYSCTL_HANDLER_ARGS)
502219180Sadrian{
503219180Sadrian	struct ath_softc *sc = arg1;
504219180Sadrian	int val = 0;
505219180Sadrian	int error;
506219180Sadrian
507219180Sadrian	error = sysctl_handle_int(oidp, &val, 0, req);
508219180Sadrian	if (error || !req->newptr)
509219180Sadrian		return error;
510219180Sadrian	if (val == 0)
511219180Sadrian		return 0;       /* Not clearing the stats is still valid */
512219180Sadrian	memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
513219180Sadrian	val = 0;
514219180Sadrian	return 0;
515219180Sadrian}
516219180Sadrian
517219180Sadrianstatic void
518219180Sadrianath_sysctl_stats_attach_rxphyerr(struct ath_softc *sc, struct sysctl_oid_list *parent)
519219180Sadrian{
520219180Sadrian	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
521219180Sadrian	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
522219180Sadrian	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
523219180Sadrian	int i;
524219180Sadrian	char sn[8];
525219180Sadrian
526219180Sadrian	tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx_phy_err", CTLFLAG_RD, NULL, "Per-code RX PHY Errors");
527219180Sadrian	child = SYSCTL_CHILDREN(tree);
528219180Sadrian	for (i = 0; i < 64; i++) {
529219180Sadrian		snprintf(sn, sizeof(sn), "%d", i);
530219180Sadrian		SYSCTL_ADD_UINT(ctx, child, OID_AUTO, sn, CTLFLAG_RD, &sc->sc_stats.ast_rx_phy[i], 0, "");
531219180Sadrian	}
532219180Sadrian}
533219180Sadrian
534219180Sadrianvoid
535219180Sadrianath_sysctl_stats_attach(struct ath_softc *sc)
536219180Sadrian{
537219180Sadrian	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
538219180Sadrian	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
539219180Sadrian	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
540219180Sadrian
541219180Sadrian	/* Create "clear" node */
542219180Sadrian	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
543219180Sadrian	    "clear_stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
544219180Sadrian	    ath_sysctl_clearstats, "I", "clear stats");
545219180Sadrian
546219180Sadrian	/* Create stats node */
547219180Sadrian	tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
548219180Sadrian	    NULL, "Statistics");
549219180Sadrian	child = SYSCTL_CHILDREN(tree);
550219180Sadrian
551219180Sadrian	/* This was generated from if_athioctl.h */
552219180Sadrian
553219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_watchdog", CTLFLAG_RD,
554219180Sadrian	    &sc->sc_stats.ast_watchdog, 0, "device reset by watchdog");
555219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_hardware", CTLFLAG_RD,
556219180Sadrian	    &sc->sc_stats.ast_hardware, 0, "fatal hardware error interrupts");
557219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bmiss", CTLFLAG_RD,
558219180Sadrian	    &sc->sc_stats.ast_bmiss, 0, "beacon miss interrupts");
559219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bmiss_phantom", CTLFLAG_RD,
560219180Sadrian	    &sc->sc_stats.ast_bmiss_phantom, 0, "beacon miss interrupts");
561219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bstuck", CTLFLAG_RD,
562219180Sadrian	    &sc->sc_stats.ast_bstuck, 0, "beacon stuck interrupts");
563219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rxorn", CTLFLAG_RD,
564219180Sadrian	    &sc->sc_stats.ast_rxorn, 0, "rx overrun interrupts");
565219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rxeol", CTLFLAG_RD,
566219180Sadrian	    &sc->sc_stats.ast_rxeol, 0, "rx eol interrupts");
567219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_txurn", CTLFLAG_RD,
568219180Sadrian	    &sc->sc_stats.ast_txurn, 0, "tx underrun interrupts");
569219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_mib", CTLFLAG_RD,
570219180Sadrian	    &sc->sc_stats.ast_mib, 0, "mib interrupts");
571219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_intrcoal", CTLFLAG_RD,
572219180Sadrian	    &sc->sc_stats.ast_intrcoal, 0, "interrupts coalesced");
573219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_packets", CTLFLAG_RD,
574219180Sadrian	    &sc->sc_stats.ast_tx_packets, 0, "packet sent on the interface");
575219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_mgmt", CTLFLAG_RD,
576219180Sadrian	    &sc->sc_stats.ast_tx_mgmt, 0, "management frames transmitted");
577219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_discard", CTLFLAG_RD,
578219180Sadrian	    &sc->sc_stats.ast_tx_discard, 0, "frames discarded prior to assoc");
579219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_qstop", CTLFLAG_RD,
580219180Sadrian	    &sc->sc_stats.ast_tx_qstop, 0, "output stopped 'cuz no buffer");
581219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_encap", CTLFLAG_RD,
582219180Sadrian	    &sc->sc_stats.ast_tx_encap, 0, "tx encapsulation failed");
583219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nonode", CTLFLAG_RD,
584219180Sadrian	    &sc->sc_stats.ast_tx_nonode, 0, "tx failed 'cuz no node");
585219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nombuf", CTLFLAG_RD,
586219180Sadrian	    &sc->sc_stats.ast_tx_nombuf, 0, "tx failed 'cuz no mbuf");
587219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nomcl", CTLFLAG_RD,
588219180Sadrian	    &sc->sc_stats.ast_tx_nomcl, 0, "tx failed 'cuz no cluster");
589219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_linear", CTLFLAG_RD,
590219180Sadrian	    &sc->sc_stats.ast_tx_linear, 0, "tx linearized to cluster");
591219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nodata", CTLFLAG_RD,
592219180Sadrian	    &sc->sc_stats.ast_tx_nodata, 0, "tx discarded empty frame");
593219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_busdma", CTLFLAG_RD,
594219180Sadrian	    &sc->sc_stats.ast_tx_busdma, 0, "tx failed for dma resrcs");
595219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_xretries", CTLFLAG_RD,
596219180Sadrian	    &sc->sc_stats.ast_tx_xretries, 0, "tx failed 'cuz too many retries");
597219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_fifoerr", CTLFLAG_RD,
598219180Sadrian	    &sc->sc_stats.ast_tx_fifoerr, 0, "tx failed 'cuz FIFO underrun");
599219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_filtered", CTLFLAG_RD,
600219180Sadrian	    &sc->sc_stats.ast_tx_filtered, 0, "tx failed 'cuz xmit filtered");
601219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_shortretry", CTLFLAG_RD,
602219180Sadrian	    &sc->sc_stats.ast_tx_shortretry, 0, "tx on-chip retries (short)");
603219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_longretry", CTLFLAG_RD,
604219180Sadrian	    &sc->sc_stats.ast_tx_longretry, 0, "tx on-chip retries (long)");
605219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_badrate", CTLFLAG_RD,
606219180Sadrian	    &sc->sc_stats.ast_tx_badrate, 0, "tx failed 'cuz bogus xmit rate");
607219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_noack", CTLFLAG_RD,
608219180Sadrian	    &sc->sc_stats.ast_tx_noack, 0, "tx frames with no ack marked");
609219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_rts", CTLFLAG_RD,
610219180Sadrian	    &sc->sc_stats.ast_tx_rts, 0, "tx frames with rts enabled");
611219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_cts", CTLFLAG_RD,
612219180Sadrian	    &sc->sc_stats.ast_tx_cts, 0, "tx frames with cts enabled");
613219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_shortpre", CTLFLAG_RD,
614219180Sadrian	    &sc->sc_stats.ast_tx_shortpre, 0, "tx frames with short preamble");
615219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_altrate", CTLFLAG_RD,
616219180Sadrian	    &sc->sc_stats.ast_tx_altrate, 0, "tx frames with alternate rate");
617219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_protect", CTLFLAG_RD,
618219180Sadrian	    &sc->sc_stats.ast_tx_protect, 0, "tx frames with protection");
619219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_ctsburst", CTLFLAG_RD,
620219180Sadrian	    &sc->sc_stats.ast_tx_ctsburst, 0, "tx frames with cts and bursting");
621219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_ctsext", CTLFLAG_RD,
622219180Sadrian	    &sc->sc_stats.ast_tx_ctsext, 0, "tx frames with cts extension");
623219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_nombuf", CTLFLAG_RD,
624219180Sadrian	    &sc->sc_stats.ast_rx_nombuf, 0, "rx setup failed 'cuz no mbuf");
625219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_busdma", CTLFLAG_RD,
626219180Sadrian	    &sc->sc_stats.ast_rx_busdma, 0, "rx setup failed for dma resrcs");
627219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_orn", CTLFLAG_RD,
628219180Sadrian	    &sc->sc_stats.ast_rx_orn, 0, "rx failed 'cuz of desc overrun");
629219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_crcerr", CTLFLAG_RD,
630219180Sadrian	    &sc->sc_stats.ast_rx_crcerr, 0, "rx failed 'cuz of bad CRC");
631219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_fifoerr", CTLFLAG_RD,
632219180Sadrian	    &sc->sc_stats.ast_rx_fifoerr, 0, "rx failed 'cuz of FIFO overrun");
633219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_badcrypt", CTLFLAG_RD,
634219180Sadrian	    &sc->sc_stats.ast_rx_badcrypt, 0, "rx failed 'cuz decryption");
635219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_badmic", CTLFLAG_RD,
636219180Sadrian	    &sc->sc_stats.ast_rx_badmic, 0, "rx failed 'cuz MIC failure");
637219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_phyerr", CTLFLAG_RD,
638219180Sadrian	    &sc->sc_stats.ast_rx_phyerr, 0, "rx failed 'cuz of PHY err");
639219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_tooshort", CTLFLAG_RD,
640219180Sadrian	    &sc->sc_stats.ast_rx_tooshort, 0, "rx discarded 'cuz frame too short");
641219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_toobig", CTLFLAG_RD,
642219180Sadrian	    &sc->sc_stats.ast_rx_toobig, 0, "rx discarded 'cuz frame too large");
643219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_packets", CTLFLAG_RD,
644219180Sadrian	    &sc->sc_stats.ast_rx_packets, 0, "packet recv on the interface");
645219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_mgt", CTLFLAG_RD,
646219180Sadrian	    &sc->sc_stats.ast_rx_mgt, 0, "management frames received");
647219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_ctl", CTLFLAG_RD,
648219180Sadrian	    &sc->sc_stats.ast_rx_ctl, 0, "rx discarded 'cuz ctl frame");
649219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_xmit", CTLFLAG_RD,
650219180Sadrian	    &sc->sc_stats.ast_be_xmit, 0, "beacons transmitted");
651219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_nombuf", CTLFLAG_RD,
652219180Sadrian	    &sc->sc_stats.ast_be_nombuf, 0, "beacon setup failed 'cuz no mbuf");
653219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_cal", CTLFLAG_RD,
654219180Sadrian	    &sc->sc_stats.ast_per_cal, 0, "periodic calibration calls");
655219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_calfail", CTLFLAG_RD,
656219180Sadrian	    &sc->sc_stats.ast_per_calfail, 0, "periodic calibration failed");
657219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_rfgain", CTLFLAG_RD,
658219180Sadrian	    &sc->sc_stats.ast_per_rfgain, 0, "periodic calibration rfgain reset");
659219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_calls", CTLFLAG_RD,
660219180Sadrian	    &sc->sc_stats.ast_rate_calls, 0, "rate control checks");
661219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_raise", CTLFLAG_RD,
662219180Sadrian	    &sc->sc_stats.ast_rate_raise, 0, "rate control raised xmit rate");
663219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_drop", CTLFLAG_RD,
664219180Sadrian	    &sc->sc_stats.ast_rate_drop, 0, "rate control dropped xmit rate");
665219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ant_defswitch", CTLFLAG_RD,
666219180Sadrian	    &sc->sc_stats.ast_ant_defswitch, 0, "rx/default antenna switches");
667219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ant_txswitch", CTLFLAG_RD,
668219180Sadrian	    &sc->sc_stats.ast_ant_txswitch, 0, "tx antenna switches");
669219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_cabq_xmit", CTLFLAG_RD,
670219180Sadrian	    &sc->sc_stats.ast_cabq_xmit, 0, "cabq frames transmitted");
671219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_cabq_busy", CTLFLAG_RD,
672219180Sadrian	    &sc->sc_stats.ast_cabq_busy, 0, "cabq found busy");
673219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_raw", CTLFLAG_RD,
674219180Sadrian	    &sc->sc_stats.ast_tx_raw, 0, "tx frames through raw api");
675219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_txok", CTLFLAG_RD,
676219180Sadrian	    &sc->sc_stats.ast_ff_txok, 0, "fast frames tx'd successfully");
677219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_txerr", CTLFLAG_RD,
678219180Sadrian	    &sc->sc_stats.ast_ff_txerr, 0, "fast frames tx'd w/ error");
679219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_rx", CTLFLAG_RD,
680219180Sadrian	    &sc->sc_stats.ast_ff_rx, 0, "fast frames rx'd");
681219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_flush", CTLFLAG_RD,
682219180Sadrian	    &sc->sc_stats.ast_ff_flush, 0, "fast frames flushed from staging q");
683219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_qfull", CTLFLAG_RD,
684219180Sadrian	    &sc->sc_stats.ast_tx_qfull, 0, "tx dropped 'cuz of queue limit");
685219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nobuf", CTLFLAG_RD,
686219180Sadrian	    &sc->sc_stats.ast_tx_nobuf, 0, "tx dropped 'cuz no ath buffer");
687219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_update", CTLFLAG_RD,
688219180Sadrian	    &sc->sc_stats.ast_tdma_update, 0, "TDMA slot timing updates");
689219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_timers", CTLFLAG_RD,
690219180Sadrian	    &sc->sc_stats.ast_tdma_timers, 0, "TDMA slot update set beacon timers");
691219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_tsf", CTLFLAG_RD,
692219180Sadrian	    &sc->sc_stats.ast_tdma_tsf, 0, "TDMA slot update set TSF");
693219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_ack", CTLFLAG_RD,
694219180Sadrian	    &sc->sc_stats.ast_tdma_ack, 0, "TDMA tx failed 'cuz ACK required");
695219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_raw_fail", CTLFLAG_RD,
696219180Sadrian	    &sc->sc_stats.ast_tx_raw_fail, 0, "raw tx failed 'cuz h/w down");
697219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nofrag", CTLFLAG_RD,
698219180Sadrian	    &sc->sc_stats.ast_tx_nofrag, 0, "tx dropped 'cuz no ath frag buffer");
699219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_missed", CTLFLAG_RD,
700219180Sadrian	    &sc->sc_stats.ast_be_missed, 0, "number of -missed- beacons");
701219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ani_cal", CTLFLAG_RD,
702219180Sadrian	    &sc->sc_stats.ast_ani_cal, 0, "number of ANI polls");
703219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_agg", CTLFLAG_RD,
704219180Sadrian	    &sc->sc_stats.ast_rx_agg, 0, "number of aggregate frames received");
705219180Sadrian
706219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_halfgi", CTLFLAG_RD,
707219180Sadrian	    &sc->sc_stats.ast_rx_halfgi, 0, "number of frames received with half-GI");
708219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_2040", CTLFLAG_RD,
709219180Sadrian	    &sc->sc_stats.ast_rx_2040, 0, "number of HT/40 frames received");
710219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_pre_crc_err", CTLFLAG_RD,
711219180Sadrian	    &sc->sc_stats.ast_rx_pre_crc_err, 0, "number of delimeter-CRC errors detected");
712219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_post_crc_err", CTLFLAG_RD,
713219180Sadrian	    &sc->sc_stats.ast_rx_post_crc_err, 0, "number of post-delimiter CRC errors detected");
714219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_decrypt_busy_err", CTLFLAG_RD,
715219180Sadrian	    &sc->sc_stats.ast_rx_decrypt_busy_err, 0, "number of frames received w/ busy decrypt engine");
716219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_hi_rx_chain", CTLFLAG_RD,
717219180Sadrian	    &sc->sc_stats.ast_rx_hi_rx_chain, 0, "");
718219180Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_htprotect", CTLFLAG_RD,
719219180Sadrian	    &sc->sc_stats.ast_tx_htprotect, 0, "HT tx frames with protection");
720220132Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_hitqueueend", CTLFLAG_RD,
721220132Sadrian	    &sc->sc_stats.ast_rx_hitqueueend, 0, "RX hit queue end");
722220772Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_timeout", CTLFLAG_RD,
723220772Sadrian	    &sc->sc_stats.ast_tx_timeout, 0, "TX Global Timeout");
724220782Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_cst", CTLFLAG_RD,
725220782Sadrian	    &sc->sc_stats.ast_tx_cst, 0, "TX Carrier Sense Timeout");
726221965Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_xtxop", CTLFLAG_RD,
727221965Sadrian	    &sc->sc_stats.ast_tx_xtxop, 0, "TX exceeded TXOP");
728221965Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_timerexpired", CTLFLAG_RD,
729221965Sadrian	    &sc->sc_stats.ast_tx_timerexpired, 0, "TX exceeded TX_TIMER register");
730221965Sadrian	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_desccfgerr", CTLFLAG_RD,
731221965Sadrian	    &sc->sc_stats.ast_tx_desccfgerr, 0, "TX Descriptor Cfg Error");
732219180Sadrian
733219180Sadrian	/* Attach the RX phy error array */
734219180Sadrian	ath_sysctl_stats_attach_rxphyerr(sc, child);
735219180Sadrian}
736223459Sadrian
737223459Sadrian/*
738223459Sadrian * This doesn't necessarily belong here (because it's HAL related, not
739223459Sadrian * driver related).
740223459Sadrian */
741223459Sadrianvoid
742223459Sadrianath_sysctl_hal_attach(struct ath_softc *sc)
743223459Sadrian{
744223459Sadrian	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
745223459Sadrian	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
746223459Sadrian	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
747223459Sadrian
748223459Sadrian	tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hal", CTLFLAG_RD,
749223459Sadrian	    NULL, "Atheros HAL parameters");
750223459Sadrian	child = SYSCTL_CHILDREN(tree);
751223459Sadrian
752223459Sadrian	sc->sc_ah->ah_config.ah_debug = 0;
753223459Sadrian	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "debug", CTLFLAG_RW,
754223459Sadrian	    &sc->sc_ah->ah_config.ah_debug, 0, "Atheros HAL debugging printfs");
755223459Sadrian
756223459Sadrian	sc->sc_ah->ah_config.ah_ar5416_biasadj = 0;
757223459Sadrian	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "ar5416_biasadj", CTLFLAG_RW,
758223459Sadrian	    &sc->sc_ah->ah_config.ah_ar5416_biasadj, 0,
759232786Sgavin	    "Enable 2GHz AR5416 direction sensitivity bias adjust");
760223459Sadrian
761223459Sadrian	sc->sc_ah->ah_config.ah_dma_beacon_response_time = 2;
762223459Sadrian	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "dma_brt", CTLFLAG_RW,
763223459Sadrian	    &sc->sc_ah->ah_config.ah_dma_beacon_response_time, 0,
764223459Sadrian	    "Atheros HAL DMA beacon response time");
765223459Sadrian
766223459Sadrian	sc->sc_ah->ah_config.ah_sw_beacon_response_time = 10;
767223459Sadrian	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "sw_brt", CTLFLAG_RW,
768223459Sadrian	    &sc->sc_ah->ah_config.ah_sw_beacon_response_time, 0,
769223459Sadrian	    "Atheros HAL software beacon response time");
770223459Sadrian
771223459Sadrian	sc->sc_ah->ah_config.ah_additional_swba_backoff = 0;
772223459Sadrian	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "swba_backoff", CTLFLAG_RW,
773223459Sadrian	    &sc->sc_ah->ah_config.ah_additional_swba_backoff, 0,
774223459Sadrian	    "Atheros HAL additional SWBA backoff time");
775223459Sadrian}
776