18735ee573
AR5416 and later NICs have more than 8 (Well, more than 6) GPIO pins. So to support rfkill on these NICs we need to bump this up or the rfkill GPIO pin may get reset to the wrong value. Noticed by: Anthony Jenkins <scoobi_doo@yahoo.com>
1168 lines
41 KiB
C
1168 lines
41 KiB
C
/*-
|
|
* Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer,
|
|
* without modification.
|
|
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
|
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
|
* redistribution must be conditioned upon including a substantially
|
|
* similar Disclaimer requirement for further binary redistribution.
|
|
*
|
|
* NO WARRANTY
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
|
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
/*
|
|
* Driver for the Atheros Wireless LAN controller.
|
|
*
|
|
* This software is derived from work of Atsushi Onoe; his contribution
|
|
* is greatly appreciated.
|
|
*/
|
|
|
|
#include "opt_inet.h"
|
|
#include "opt_ath.h"
|
|
#include "opt_wlan.h"
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/sysctl.h>
|
|
#include <sys/mbuf.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/lock.h>
|
|
#include <sys/mutex.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/sockio.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/callout.h>
|
|
#include <sys/bus.h>
|
|
#include <sys/endian.h>
|
|
#include <sys/kthread.h>
|
|
#include <sys/taskqueue.h>
|
|
#include <sys/priv.h>
|
|
|
|
#include <machine/bus.h>
|
|
|
|
#include <net/if.h>
|
|
#include <net/if_var.h>
|
|
#include <net/if_dl.h>
|
|
#include <net/if_media.h>
|
|
#include <net/if_types.h>
|
|
#include <net/if_arp.h>
|
|
#include <net/ethernet.h>
|
|
#include <net/if_llc.h>
|
|
|
|
#include <net80211/ieee80211_var.h>
|
|
#include <net80211/ieee80211_regdomain.h>
|
|
#ifdef IEEE80211_SUPPORT_SUPERG
|
|
#include <net80211/ieee80211_superg.h>
|
|
#endif
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
|
#include <net80211/ieee80211_tdma.h>
|
|
#endif
|
|
|
|
#include <net/bpf.h>
|
|
|
|
#ifdef INET
|
|
#include <netinet/in.h>
|
|
#include <netinet/if_ether.h>
|
|
#endif
|
|
|
|
#include <dev/ath/if_athvar.h>
|
|
#include <dev/ath/ath_hal/ah_devid.h> /* XXX for softled */
|
|
#include <dev/ath/ath_hal/ah_diagcodes.h>
|
|
|
|
#include <dev/ath/if_ath_debug.h>
|
|
#include <dev/ath/if_ath_led.h>
|
|
#include <dev/ath/if_ath_misc.h>
|
|
#include <dev/ath/if_ath_tx.h>
|
|
#include <dev/ath/if_ath_sysctl.h>
|
|
|
|
#ifdef ATH_TX99_DIAG
|
|
#include <dev/ath/ath_tx99/ath_tx99.h>
|
|
#endif
|
|
|
|
#ifdef ATH_DEBUG_ALQ
|
|
#include <dev/ath/if_ath_alq.h>
|
|
#endif
|
|
|
|
static int
|
|
ath_sysctl_slottime(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int slottime;
|
|
int error;
|
|
|
|
ATH_LOCK(sc);
|
|
ath_power_set_power_state(sc, HAL_PM_AWAKE);
|
|
slottime = ath_hal_getslottime(sc->sc_ah);
|
|
ATH_UNLOCK(sc);
|
|
|
|
error = sysctl_handle_int(oidp, &slottime, 0, req);
|
|
if (error || !req->newptr)
|
|
goto finish;
|
|
|
|
error = !ath_hal_setslottime(sc->sc_ah, slottime) ? EINVAL : 0;
|
|
|
|
finish:
|
|
ATH_LOCK(sc);
|
|
ath_power_restore_power_state(sc);
|
|
ATH_UNLOCK(sc);
|
|
|
|
return error;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_acktimeout(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int acktimeout = ath_hal_getacktimeout(sc->sc_ah);
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &acktimeout, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
return !ath_hal_setacktimeout(sc->sc_ah, acktimeout) ? EINVAL : 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_ctstimeout(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int ctstimeout = ath_hal_getctstimeout(sc->sc_ah);
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &ctstimeout, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
return !ath_hal_setctstimeout(sc->sc_ah, ctstimeout) ? EINVAL : 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_softled(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int softled = sc->sc_softled;
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &softled, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
softled = (softled != 0);
|
|
if (softled != sc->sc_softled) {
|
|
if (softled) {
|
|
/* NB: handle any sc_ledpin change */
|
|
ath_led_config(sc);
|
|
}
|
|
sc->sc_softled = softled;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_ledpin(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int ledpin = sc->sc_ledpin;
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &ledpin, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
if (ledpin != sc->sc_ledpin) {
|
|
sc->sc_ledpin = ledpin;
|
|
if (sc->sc_softled) {
|
|
ath_led_config(sc);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_hardled(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int hardled = sc->sc_hardled;
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &hardled, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
hardled = (hardled != 0);
|
|
if (hardled != sc->sc_hardled) {
|
|
if (hardled) {
|
|
/* NB: handle any sc_ledpin change */
|
|
ath_led_config(sc);
|
|
}
|
|
sc->sc_hardled = hardled;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_txantenna(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int txantenna = ath_hal_getantennaswitch(sc->sc_ah);
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &txantenna, 0, req);
|
|
if (!error && req->newptr) {
|
|
/* XXX assumes 2 antenna ports */
|
|
if (txantenna < HAL_ANT_VARIABLE || txantenna > HAL_ANT_FIXED_B)
|
|
return EINVAL;
|
|
ath_hal_setantennaswitch(sc->sc_ah, txantenna);
|
|
/*
|
|
* NB: with the switch locked this isn't meaningful,
|
|
* but set it anyway so things like radiotap get
|
|
* consistent info in their data.
|
|
*/
|
|
sc->sc_txantenna = txantenna;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_rxantenna(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int defantenna = ath_hal_getdefantenna(sc->sc_ah);
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &defantenna, 0, req);
|
|
if (!error && req->newptr)
|
|
ath_hal_setdefantenna(sc->sc_ah, defantenna);
|
|
return error;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_diversity(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int diversity = ath_hal_getdiversity(sc->sc_ah);
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &diversity, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
if (!ath_hal_setdiversity(sc->sc_ah, diversity))
|
|
return EINVAL;
|
|
sc->sc_diversity = diversity;
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_diag(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int32_t diag;
|
|
int error;
|
|
|
|
if (!ath_hal_getdiag(sc->sc_ah, &diag))
|
|
return EINVAL;
|
|
error = sysctl_handle_int(oidp, &diag, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
return !ath_hal_setdiag(sc->sc_ah, diag) ? EINVAL : 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
u_int32_t scale;
|
|
int error;
|
|
|
|
(void) ath_hal_gettpscale(sc->sc_ah, &scale);
|
|
error = sysctl_handle_int(oidp, &scale, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
return !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL :
|
|
(ifp->if_drv_flags & IFF_DRV_RUNNING) ?
|
|
ath_reset(ifp, ATH_RESET_NOLOSS) : 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_tpc(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int tpc = ath_hal_gettpc(sc->sc_ah);
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &tpc, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
return !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
u_int rfkill = ath_hal_getrfkill(ah);
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &rfkill, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
if (rfkill == ath_hal_getrfkill(ah)) /* unchanged */
|
|
return 0;
|
|
if (!ath_hal_setrfkill(ah, rfkill))
|
|
return EINVAL;
|
|
return (ifp->if_drv_flags & IFF_DRV_RUNNING) ?
|
|
ath_reset(ifp, ATH_RESET_FULL) : 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_txagg(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int i, t, param = 0;
|
|
int error;
|
|
struct ath_buf *bf;
|
|
|
|
error = sysctl_handle_int(oidp, ¶m, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
|
|
if (param != 1)
|
|
return 0;
|
|
|
|
printf("no tx bufs (empty list): %d\n", sc->sc_stats.ast_tx_getnobuf);
|
|
printf("no tx bufs (was busy): %d\n", sc->sc_stats.ast_tx_getbusybuf);
|
|
|
|
printf("aggr single packet: %d\n",
|
|
sc->sc_aggr_stats.aggr_single_pkt);
|
|
printf("aggr single packet w/ BAW closed: %d\n",
|
|
sc->sc_aggr_stats.aggr_baw_closed_single_pkt);
|
|
printf("aggr non-baw packet: %d\n",
|
|
sc->sc_aggr_stats.aggr_nonbaw_pkt);
|
|
printf("aggr aggregate packet: %d\n",
|
|
sc->sc_aggr_stats.aggr_aggr_pkt);
|
|
printf("aggr single packet low hwq: %d\n",
|
|
sc->sc_aggr_stats.aggr_low_hwq_single_pkt);
|
|
printf("aggr single packet RTS aggr limited: %d\n",
|
|
sc->sc_aggr_stats.aggr_rts_aggr_limited);
|
|
printf("aggr sched, no work: %d\n",
|
|
sc->sc_aggr_stats.aggr_sched_nopkt);
|
|
for (i = 0; i < 64; i++) {
|
|
printf("%2d: %10d ", i, sc->sc_aggr_stats.aggr_pkts[i]);
|
|
if (i % 4 == 3)
|
|
printf("\n");
|
|
}
|
|
printf("\n");
|
|
|
|
for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
|
|
if (ATH_TXQ_SETUP(sc, i)) {
|
|
printf("HW TXQ %d: axq_depth=%d, axq_aggr_depth=%d, "
|
|
"axq_fifo_depth=%d, holdingbf=%p\n",
|
|
i,
|
|
sc->sc_txq[i].axq_depth,
|
|
sc->sc_txq[i].axq_aggr_depth,
|
|
sc->sc_txq[i].axq_fifo_depth,
|
|
sc->sc_txq[i].axq_holdingbf);
|
|
}
|
|
}
|
|
|
|
i = t = 0;
|
|
ATH_TXBUF_LOCK(sc);
|
|
TAILQ_FOREACH(bf, &sc->sc_txbuf, bf_list) {
|
|
if (bf->bf_flags & ATH_BUF_BUSY) {
|
|
printf("Busy: %d\n", t);
|
|
i++;
|
|
}
|
|
t++;
|
|
}
|
|
ATH_TXBUF_UNLOCK(sc);
|
|
printf("Total TX buffers: %d; Total TX buffers busy: %d (%d)\n",
|
|
t, i, sc->sc_txbuf_cnt);
|
|
|
|
i = t = 0;
|
|
ATH_TXBUF_LOCK(sc);
|
|
TAILQ_FOREACH(bf, &sc->sc_txbuf_mgmt, bf_list) {
|
|
if (bf->bf_flags & ATH_BUF_BUSY) {
|
|
printf("Busy: %d\n", t);
|
|
i++;
|
|
}
|
|
t++;
|
|
}
|
|
ATH_TXBUF_UNLOCK(sc);
|
|
printf("Total mgmt TX buffers: %d; Total mgmt TX buffers busy: %d\n",
|
|
t, i);
|
|
|
|
ATH_RX_LOCK(sc);
|
|
for (i = 0; i < 2; i++) {
|
|
printf("%d: fifolen: %d/%d; head=%d; tail=%d; m_pending=%p, m_holdbf=%p\n",
|
|
i,
|
|
sc->sc_rxedma[i].m_fifo_depth,
|
|
sc->sc_rxedma[i].m_fifolen,
|
|
sc->sc_rxedma[i].m_fifo_head,
|
|
sc->sc_rxedma[i].m_fifo_tail,
|
|
sc->sc_rxedma[i].m_rxpending,
|
|
sc->sc_rxedma[i].m_holdbf);
|
|
}
|
|
i = 0;
|
|
TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
|
|
i++;
|
|
}
|
|
printf("Total RX buffers in free list: %d buffers\n",
|
|
i);
|
|
ATH_RX_UNLOCK(sc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int rfsilent;
|
|
int error;
|
|
|
|
(void) ath_hal_getrfsilent(sc->sc_ah, &rfsilent);
|
|
error = sysctl_handle_int(oidp, &rfsilent, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent))
|
|
return EINVAL;
|
|
/*
|
|
* Earlier chips (< AR5212) have up to 8 GPIO
|
|
* pins exposed.
|
|
*
|
|
* AR5416 and later chips have many more GPIO
|
|
* pins (up to 16) so the mask is expanded to
|
|
* four bits.
|
|
*/
|
|
sc->sc_rfsilentpin = rfsilent & 0x3c;
|
|
sc->sc_rfsilentpol = (rfsilent & 0x2) != 0;
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_tpack(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int32_t tpack;
|
|
int error;
|
|
|
|
(void) ath_hal_gettpack(sc->sc_ah, &tpack);
|
|
error = sysctl_handle_int(oidp, &tpack, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
return !ath_hal_settpack(sc->sc_ah, tpack) ? EINVAL : 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_tpcts(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
u_int32_t tpcts;
|
|
int error;
|
|
|
|
(void) ath_hal_gettpcts(sc->sc_ah, &tpcts);
|
|
error = sysctl_handle_int(oidp, &tpcts, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
return !ath_hal_settpcts(sc->sc_ah, tpcts) ? EINVAL : 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int intmit, error;
|
|
|
|
intmit = ath_hal_getintmit(sc->sc_ah);
|
|
error = sysctl_handle_int(oidp, &intmit, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
|
|
/* reusing error; 1 here means "good"; 0 means "fail" */
|
|
error = ath_hal_setintmit(sc->sc_ah, intmit);
|
|
if (! error)
|
|
return EINVAL;
|
|
|
|
/*
|
|
* Reset the hardware here - disabling ANI in the HAL
|
|
* doesn't reset ANI related registers, so it'll leave
|
|
* things in an inconsistent state.
|
|
*/
|
|
if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
|
|
ath_reset(sc->sc_ifp, ATH_RESET_NOLOSS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
|
static int
|
|
ath_sysctl_setcca(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int setcca, error;
|
|
|
|
setcca = sc->sc_setcca;
|
|
error = sysctl_handle_int(oidp, &setcca, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
sc->sc_setcca = (setcca != 0);
|
|
return 0;
|
|
}
|
|
#endif /* IEEE80211_SUPPORT_TDMA */
|
|
|
|
static int
|
|
ath_sysctl_forcebstuck(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int val = 0;
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &val, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
if (val == 0)
|
|
return 0;
|
|
|
|
taskqueue_enqueue_fast(sc->sc_tq, &sc->sc_bstucktask);
|
|
val = 0;
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_hangcheck(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int val = 0;
|
|
int error;
|
|
uint32_t mask = 0xffffffff;
|
|
uint32_t *sp;
|
|
uint32_t rsize;
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
error = sysctl_handle_int(oidp, &val, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
if (val == 0)
|
|
return 0;
|
|
|
|
/* Do a hang check */
|
|
if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS,
|
|
&mask, sizeof(mask),
|
|
(void *) &sp, &rsize))
|
|
return (0);
|
|
device_printf(sc->sc_dev, "%s: sp=0x%08x\n", __func__, *sp);
|
|
|
|
val = 0;
|
|
return 0;
|
|
}
|
|
|
|
#ifdef ATH_DEBUG_ALQ
|
|
static int
|
|
ath_sysctl_alq_log(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int error, enable;
|
|
|
|
enable = (sc->sc_alq.sc_alq_isactive);
|
|
|
|
error = sysctl_handle_int(oidp, &enable, 0, req);
|
|
if (error || !req->newptr)
|
|
return (error);
|
|
else if (enable)
|
|
error = if_ath_alq_start(&sc->sc_alq);
|
|
else
|
|
error = if_ath_alq_stop(&sc->sc_alq);
|
|
return (error);
|
|
}
|
|
|
|
/*
|
|
* Attach the ALQ debugging if required.
|
|
*/
|
|
static void
|
|
ath_sysctl_alq_attach(struct ath_softc *sc)
|
|
{
|
|
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
|
|
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
|
|
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
|
|
|
|
tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "alq", CTLFLAG_RD,
|
|
NULL, "Atheros ALQ logging parameters");
|
|
child = SYSCTL_CHILDREN(tree);
|
|
|
|
SYSCTL_ADD_STRING(ctx, child, OID_AUTO, "filename",
|
|
CTLFLAG_RW, sc->sc_alq.sc_alq_filename, 0, "ALQ filename");
|
|
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"enable", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_alq_log, "I", "");
|
|
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"debugmask", CTLFLAG_RW, &sc->sc_alq.sc_alq_debug, 0,
|
|
"ALQ debug mask");
|
|
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"numlost", CTLFLAG_RW, &sc->sc_alq.sc_alq_numlost, 0,
|
|
"number lost");
|
|
}
|
|
#endif /* ATH_DEBUG_ALQ */
|
|
|
|
void
|
|
ath_sysctlattach(struct ath_softc *sc)
|
|
{
|
|
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
|
|
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"countrycode", CTLFLAG_RD, &sc->sc_eecc, 0,
|
|
"EEPROM country code");
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"regdomain", CTLFLAG_RD, &sc->sc_eerd, 0,
|
|
"EEPROM regdomain code");
|
|
#ifdef ATH_DEBUG
|
|
SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"debug", CTLFLAG_RW, &sc->sc_debug,
|
|
"control debugging printfs");
|
|
#endif
|
|
#ifdef ATH_DEBUG_ALQ
|
|
SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"ktrdebug", CTLFLAG_RW, &sc->sc_ktrdebug,
|
|
"control debugging KTR");
|
|
#endif /* ATH_DEBUG_ALQ */
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"slottime", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_slottime, "I", "802.11 slot time (us)");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"acktimeout", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_acktimeout, "I", "802.11 ACK timeout (us)");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"ctstimeout", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_ctstimeout, "I", "802.11 CTS timeout (us)");
|
|
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"softled", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_softled, "I", "enable/disable software LED support");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"ledpin", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_ledpin, "I", "GPIO pin connected to LED");
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"ledon", CTLFLAG_RW, &sc->sc_ledon, 0,
|
|
"setting to turn LED on");
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"ledidle", CTLFLAG_RW, &sc->sc_ledidle, 0,
|
|
"idle time for inactivity LED (ticks)");
|
|
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"hardled", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_hardled, "I", "enable/disable hardware LED support");
|
|
/* XXX Laziness - configure pins, then flip hardled off/on */
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"led_net_pin", CTLFLAG_RW, &sc->sc_led_net_pin, 0,
|
|
"MAC Network LED pin, or -1 to disable");
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"led_pwr_pin", CTLFLAG_RW, &sc->sc_led_pwr_pin, 0,
|
|
"MAC Power LED pin, or -1 to disable");
|
|
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"txantenna", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_txantenna, "I", "antenna switch");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"rxantenna", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_rxantenna, "I", "default/rx antenna");
|
|
if (ath_hal_hasdiversity(ah))
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"diversity", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_diversity, "I", "antenna diversity");
|
|
sc->sc_txintrperiod = ATH_TXINTR_PERIOD;
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"txintrperiod", CTLFLAG_RW, &sc->sc_txintrperiod, 0,
|
|
"tx descriptor batching");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"diag", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_diag, "I", "h/w diagnostic control");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"tpscale", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_tpscale, "I", "tx power scaling");
|
|
if (ath_hal_hastpc(ah)) {
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"tpc", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_tpc, "I", "enable/disable per-packet TPC");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"tpack", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_tpack, "I", "tx power for ack frames");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"tpcts", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_tpcts, "I", "tx power for cts frames");
|
|
}
|
|
if (ath_hal_hasrfsilent(ah)) {
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"rfsilent", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_rfsilent, "I", "h/w RF silent config");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"rfkill", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_rfkill, "I", "enable/disable RF kill switch");
|
|
}
|
|
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"txagg", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_txagg, "I", "");
|
|
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"forcebstuck", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_forcebstuck, "I", "");
|
|
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"hangcheck", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_hangcheck, "I", "");
|
|
|
|
if (ath_hal_hasintmit(ah)) {
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_intmit, "I", "interference mitigation");
|
|
}
|
|
sc->sc_monpass = HAL_RXERR_DECRYPT | HAL_RXERR_MIC;
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"monpass", CTLFLAG_RW, &sc->sc_monpass, 0,
|
|
"mask of error frames to pass when monitoring");
|
|
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"hwq_limit_nonaggr", CTLFLAG_RW, &sc->sc_hwq_limit_nonaggr, 0,
|
|
"Hardware non-AMPDU queue depth before software-queuing TX frames");
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"hwq_limit_aggr", CTLFLAG_RW, &sc->sc_hwq_limit_aggr, 0,
|
|
"Hardware AMPDU queue depth before software-queuing TX frames");
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"tid_hwq_lo", CTLFLAG_RW, &sc->sc_tid_hwq_lo, 0,
|
|
"");
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"tid_hwq_hi", CTLFLAG_RW, &sc->sc_tid_hwq_hi, 0,
|
|
"");
|
|
|
|
/* Aggregate length twiddles */
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"aggr_limit", CTLFLAG_RW, &sc->sc_aggr_limit, 0,
|
|
"Maximum A-MPDU size, or 0 for 'default'");
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"rts_aggr_limit", CTLFLAG_RW, &sc->sc_rts_aggr_limit, 0,
|
|
"Maximum A-MPDU size for RTS-protected frames, or '0' "
|
|
"for default");
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"delim_min_pad", CTLFLAG_RW, &sc->sc_delim_min_pad, 0,
|
|
"Enforce a minimum number of delimiters per A-MPDU "
|
|
" sub-frame");
|
|
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"txq_data_minfree", CTLFLAG_RW, &sc->sc_txq_data_minfree,
|
|
0, "Minimum free buffers before adding a data frame"
|
|
" to the TX queue");
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"txq_mcastq_maxdepth", CTLFLAG_RW,
|
|
&sc->sc_txq_mcastq_maxdepth, 0,
|
|
"Maximum buffer depth for multicast/broadcast frames");
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"txq_node_maxdepth", CTLFLAG_RW,
|
|
&sc->sc_txq_node_maxdepth, 0,
|
|
"Maximum buffer depth for a single node");
|
|
|
|
#if 0
|
|
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"cabq_enable", CTLFLAG_RW,
|
|
&sc->sc_cabq_enable, 0,
|
|
"Whether to transmit on the CABQ or not");
|
|
#endif
|
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
|
if (ath_hal_macversion(ah) > 0x78) {
|
|
sc->sc_tdmadbaprep = 2;
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"dbaprep", CTLFLAG_RW, &sc->sc_tdmadbaprep, 0,
|
|
"TDMA DBA preparation time");
|
|
sc->sc_tdmaswbaprep = 10;
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"swbaprep", CTLFLAG_RW, &sc->sc_tdmaswbaprep, 0,
|
|
"TDMA SWBA preparation time");
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"guardtime", CTLFLAG_RW, &sc->sc_tdmaguard, 0,
|
|
"TDMA slot guard time");
|
|
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"superframe", CTLFLAG_RD, &sc->sc_tdmabintval, 0,
|
|
"TDMA calculated super frame");
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"setcca", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_setcca, "I", "enable CCA control");
|
|
}
|
|
#endif
|
|
|
|
#ifdef ATH_DEBUG_ALQ
|
|
ath_sysctl_alq_attach(sc);
|
|
#endif
|
|
}
|
|
|
|
static int
|
|
ath_sysctl_clearstats(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct ath_softc *sc = arg1;
|
|
int val = 0;
|
|
int error;
|
|
|
|
error = sysctl_handle_int(oidp, &val, 0, req);
|
|
if (error || !req->newptr)
|
|
return error;
|
|
if (val == 0)
|
|
return 0; /* Not clearing the stats is still valid */
|
|
memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
|
|
memset(&sc->sc_aggr_stats, 0, sizeof(sc->sc_aggr_stats));
|
|
memset(&sc->sc_intr_stats, 0, sizeof(sc->sc_intr_stats));
|
|
|
|
val = 0;
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
ath_sysctl_stats_attach_rxphyerr(struct ath_softc *sc, struct sysctl_oid_list *parent)
|
|
{
|
|
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
|
|
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
|
|
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
|
|
int i;
|
|
char sn[8];
|
|
|
|
tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx_phy_err", CTLFLAG_RD, NULL, "Per-code RX PHY Errors");
|
|
child = SYSCTL_CHILDREN(tree);
|
|
for (i = 0; i < 64; i++) {
|
|
snprintf(sn, sizeof(sn), "%d", i);
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, sn, CTLFLAG_RD, &sc->sc_stats.ast_rx_phy[i], 0, "");
|
|
}
|
|
}
|
|
|
|
static void
|
|
ath_sysctl_stats_attach_intr(struct ath_softc *sc,
|
|
struct sysctl_oid_list *parent)
|
|
{
|
|
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
|
|
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
|
|
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
|
|
int i;
|
|
char sn[8];
|
|
|
|
tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "sync_intr",
|
|
CTLFLAG_RD, NULL, "Sync interrupt statistics");
|
|
child = SYSCTL_CHILDREN(tree);
|
|
for (i = 0; i < 32; i++) {
|
|
snprintf(sn, sizeof(sn), "%d", i);
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, sn, CTLFLAG_RD,
|
|
&sc->sc_intr_stats.sync_intr[i], 0, "");
|
|
}
|
|
}
|
|
|
|
void
|
|
ath_sysctl_stats_attach(struct ath_softc *sc)
|
|
{
|
|
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
|
|
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
|
|
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
|
|
|
|
/* Create "clear" node */
|
|
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
|
"clear_stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
|
|
ath_sysctl_clearstats, "I", "clear stats");
|
|
|
|
/* Create stats node */
|
|
tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
|
|
NULL, "Statistics");
|
|
child = SYSCTL_CHILDREN(tree);
|
|
|
|
/* This was generated from if_athioctl.h */
|
|
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_watchdog", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_watchdog, 0, "device reset by watchdog");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_hardware", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_hardware, 0, "fatal hardware error interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bmiss", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_bmiss, 0, "beacon miss interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bmiss_phantom", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_bmiss_phantom, 0, "beacon miss interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_bstuck", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_bstuck, 0, "beacon stuck interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rxorn", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rxorn, 0, "rx overrun interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rxeol", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rxeol, 0, "rx eol interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_txurn", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_txurn, 0, "tx underrun interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_mib", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_mib, 0, "mib interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_intrcoal", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_intrcoal, 0, "interrupts coalesced");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_packets", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_packets, 0, "packet sent on the interface");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_mgmt", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_mgmt, 0, "management frames transmitted");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_discard", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_discard, 0, "frames discarded prior to assoc");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_qstop", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_qstop, 0, "output stopped 'cuz no buffer");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_encap", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_encap, 0, "tx encapsulation failed");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nonode", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_nonode, 0, "tx failed 'cuz no node");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nombuf", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_nombuf, 0, "tx failed 'cuz no mbuf");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nomcl", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_nomcl, 0, "tx failed 'cuz no cluster");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_linear", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_linear, 0, "tx linearized to cluster");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nodata", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_nodata, 0, "tx discarded empty frame");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_busdma", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_busdma, 0, "tx failed for dma resrcs");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_xretries", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_xretries, 0, "tx failed 'cuz too many retries");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_fifoerr", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_fifoerr, 0, "tx failed 'cuz FIFO underrun");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_filtered", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_filtered, 0, "tx failed 'cuz xmit filtered");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_shortretry", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_shortretry, 0, "tx on-chip retries (short)");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_longretry", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_longretry, 0, "tx on-chip retries (long)");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_badrate", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_badrate, 0, "tx failed 'cuz bogus xmit rate");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_noack", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_noack, 0, "tx frames with no ack marked");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_rts", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_rts, 0, "tx frames with rts enabled");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_cts", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_cts, 0, "tx frames with cts enabled");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_shortpre", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_shortpre, 0, "tx frames with short preamble");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_altrate", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_altrate, 0, "tx frames with alternate rate");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_protect", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_protect, 0, "tx frames with protection");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_ctsburst", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_ctsburst, 0, "tx frames with cts and bursting");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_ctsext", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_ctsext, 0, "tx frames with cts extension");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_nombuf", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_nombuf, 0, "rx setup failed 'cuz no mbuf");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_busdma", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_busdma, 0, "rx setup failed for dma resrcs");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_orn", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_orn, 0, "rx failed 'cuz of desc overrun");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_crcerr", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_crcerr, 0, "rx failed 'cuz of bad CRC");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_fifoerr", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_fifoerr, 0, "rx failed 'cuz of FIFO overrun");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_badcrypt", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_badcrypt, 0, "rx failed 'cuz decryption");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_badmic", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_badmic, 0, "rx failed 'cuz MIC failure");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_phyerr", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_phyerr, 0, "rx failed 'cuz of PHY err");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_tooshort", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_tooshort, 0, "rx discarded 'cuz frame too short");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_toobig", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_toobig, 0, "rx discarded 'cuz frame too large");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_packets", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_packets, 0, "packet recv on the interface");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_mgt", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_mgt, 0, "management frames received");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_ctl", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_ctl, 0, "rx discarded 'cuz ctl frame");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_xmit", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_be_xmit, 0, "beacons transmitted");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_nombuf", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_be_nombuf, 0, "beacon setup failed 'cuz no mbuf");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_cal", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_per_cal, 0, "periodic calibration calls");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_calfail", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_per_calfail, 0, "periodic calibration failed");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_per_rfgain", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_per_rfgain, 0, "periodic calibration rfgain reset");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_calls", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rate_calls, 0, "rate control checks");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_raise", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rate_raise, 0, "rate control raised xmit rate");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rate_drop", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rate_drop, 0, "rate control dropped xmit rate");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ant_defswitch", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_ant_defswitch, 0, "rx/default antenna switches");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ant_txswitch", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_ant_txswitch, 0, "tx antenna switches");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_cabq_xmit", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_cabq_xmit, 0, "cabq frames transmitted");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_cabq_busy", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_cabq_busy, 0, "cabq found busy");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_raw", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_raw, 0, "tx frames through raw api");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_txok", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_ff_txok, 0, "fast frames tx'd successfully");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_txerr", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_ff_txerr, 0, "fast frames tx'd w/ error");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_rx", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_ff_rx, 0, "fast frames rx'd");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ff_flush", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_ff_flush, 0, "fast frames flushed from staging q");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_qfull", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_qfull, 0, "tx dropped 'cuz of queue limit");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nobuf", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_nobuf, 0, "tx dropped 'cuz no ath buffer");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_update", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tdma_update, 0, "TDMA slot timing updates");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_timers", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tdma_timers, 0, "TDMA slot update set beacon timers");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_tsf", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tdma_tsf, 0, "TDMA slot update set TSF");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tdma_ack", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tdma_ack, 0, "TDMA tx failed 'cuz ACK required");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_raw_fail", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_raw_fail, 0, "raw tx failed 'cuz h/w down");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_nofrag", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_nofrag, 0, "tx dropped 'cuz no ath frag buffer");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_be_missed", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_be_missed, 0, "number of -missed- beacons");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_ani_cal", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_ani_cal, 0, "number of ANI polls");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_agg", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_agg, 0, "number of aggregate frames received");
|
|
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_halfgi", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_halfgi, 0, "number of frames received with half-GI");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_2040", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_2040, 0, "number of HT/40 frames received");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_pre_crc_err", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_pre_crc_err, 0, "number of delimeter-CRC errors detected");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_post_crc_err", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_post_crc_err, 0, "number of post-delimiter CRC errors detected");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_decrypt_busy_err", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_decrypt_busy_err, 0, "number of frames received w/ busy decrypt engine");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_hi_rx_chain", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_hi_rx_chain, 0, "");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_htprotect", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_htprotect, 0, "HT tx frames with protection");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_hitqueueend", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_hitqueueend, 0, "RX hit queue end");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_timeout", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_timeout, 0, "TX Global Timeout");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_cst", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_cst, 0, "TX Carrier Sense Timeout");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_xtxop", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_xtxop, 0, "TX exceeded TXOP");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_timerexpired", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_timerexpired, 0, "TX exceeded TX_TIMER register");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_desccfgerr", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_desccfgerr, 0, "TX Descriptor Cfg Error");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_swretries", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_swretries, 0, "TX software retry count");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_swretrymax", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_swretrymax, 0, "TX software retry max reached");
|
|
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_data_underrun", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_data_underrun, 0, "");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_delim_underrun", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_delim_underrun, 0, "");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_aggr_failall", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_aggr_failall, 0,
|
|
"Number of aggregate TX failures (whole frame)");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_aggr_ok", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_aggr_ok, 0,
|
|
"Number of aggregate TX OK completions (subframe)");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_aggr_fail", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_aggr_fail, 0,
|
|
"Number of aggregate TX failures (subframe)");
|
|
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_intr", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_intr, 0, "RX interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_intr", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_intr, 0, "TX interrupts");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_mcastq_overflow",
|
|
CTLFLAG_RD, &sc->sc_stats.ast_tx_mcastq_overflow, 0,
|
|
"Number of multicast frames exceeding maximum mcast queue depth");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_keymiss", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_rx_keymiss, 0, "");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_tx_swfiltered", CTLFLAG_RD,
|
|
&sc->sc_stats.ast_tx_swfiltered, 0, "");
|
|
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "ast_rx_stbc",
|
|
CTLFLAG_RD, &sc->sc_stats.ast_rx_stbc, 0,
|
|
"Number of STBC frames received");
|
|
|
|
/* Attach the RX phy error array */
|
|
ath_sysctl_stats_attach_rxphyerr(sc, child);
|
|
|
|
/* Attach the interrupt statistics array */
|
|
ath_sysctl_stats_attach_intr(sc, child);
|
|
}
|
|
|
|
/*
|
|
* This doesn't necessarily belong here (because it's HAL related, not
|
|
* driver related).
|
|
*/
|
|
void
|
|
ath_sysctl_hal_attach(struct ath_softc *sc)
|
|
{
|
|
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
|
|
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
|
|
struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
|
|
|
|
tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hal", CTLFLAG_RD,
|
|
NULL, "Atheros HAL parameters");
|
|
child = SYSCTL_CHILDREN(tree);
|
|
|
|
sc->sc_ah->ah_config.ah_debug = 0;
|
|
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "debug", CTLFLAG_RW,
|
|
&sc->sc_ah->ah_config.ah_debug, 0, "Atheros HAL debugging printfs");
|
|
|
|
sc->sc_ah->ah_config.ah_ar5416_biasadj = 0;
|
|
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "ar5416_biasadj", CTLFLAG_RW,
|
|
&sc->sc_ah->ah_config.ah_ar5416_biasadj, 0,
|
|
"Enable 2GHz AR5416 direction sensitivity bias adjust");
|
|
|
|
sc->sc_ah->ah_config.ah_dma_beacon_response_time = 2;
|
|
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "dma_brt", CTLFLAG_RW,
|
|
&sc->sc_ah->ah_config.ah_dma_beacon_response_time, 0,
|
|
"Atheros HAL DMA beacon response time");
|
|
|
|
sc->sc_ah->ah_config.ah_sw_beacon_response_time = 10;
|
|
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "sw_brt", CTLFLAG_RW,
|
|
&sc->sc_ah->ah_config.ah_sw_beacon_response_time, 0,
|
|
"Atheros HAL software beacon response time");
|
|
|
|
sc->sc_ah->ah_config.ah_additional_swba_backoff = 0;
|
|
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "swba_backoff", CTLFLAG_RW,
|
|
&sc->sc_ah->ah_config.ah_additional_swba_backoff, 0,
|
|
"Atheros HAL additional SWBA backoff time");
|
|
|
|
sc->sc_ah->ah_config.ah_force_full_reset = 0;
|
|
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "force_full_reset", CTLFLAG_RW,
|
|
&sc->sc_ah->ah_config.ah_force_full_reset, 0,
|
|
"Force full chip reset rather than a warm reset");
|
|
|
|
/*
|
|
* This is initialised by the driver.
|
|
*/
|
|
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "serialise_reg_war", CTLFLAG_RW,
|
|
&sc->sc_ah->ah_config.ah_serialise_reg_war, 0,
|
|
"Force register access serialisation");
|
|
}
|