summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2012-11-08 18:11:31 +0000
committeradrian <adrian@FreeBSD.org>2012-11-08 18:11:31 +0000
commit2092e733094d0625768a248a7322b6457b81ae8f (patch)
tree5748256693582a5156ed3a762f0252b6854672b2
parent58a78bc1d751c4b99a36f956bf35766de093ab59 (diff)
downloadFreeBSD-src-2092e733094d0625768a248a7322b6457b81ae8f.zip
FreeBSD-src-2092e733094d0625768a248a7322b6457b81ae8f.tar.gz
Add some hooks into the driver to attach, detach and record EDMA descriptor
events. This is primarily for the TX EDMA and TX EDMA completion. I haven't yet tied it into the EDMA RX path or the legacy TX/RX path. Things that I don't quite like: * Make the pointer type 'void' in ath_softc and have if_ath_alq*() return a malloc'ed buffer. That would remove the need to include if_ath_alq.h in if_athvar.h. * The sysctl setup needs to be cleaned up.
-rw-r--r--sys/dev/ath/if_ath_rx.c4
-rw-r--r--sys/dev/ath/if_ath_rx_edma.c11
-rw-r--r--sys/dev/ath/if_ath_sysctl.c55
-rw-r--r--sys/dev/ath/if_ath_tx.c4
-rw-r--r--sys/dev/ath/if_ath_tx_edma.c59
-rw-r--r--sys/dev/ath/if_athvar.h8
6 files changed, 133 insertions, 8 deletions
diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c
index d614d5b..ff160b9 100644
--- a/sys/dev/ath/if_ath_rx.c
+++ b/sys/dev/ath/if_ath_rx.c
@@ -115,6 +115,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/ath_tx99/ath_tx99.h>
#endif
+#ifdef ATH_DEBUG_ALQ
+#include <dev/ath/if_ath_alq.h>
+#endif
+
/*
* Calculate the receive filter according to the
* operating mode and state:
diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c
index 7110b74..dc7fd9a 100644
--- a/sys/dev/ath/if_ath_rx_edma.c
+++ b/sys/dev/ath/if_ath_rx_edma.c
@@ -117,6 +117,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/if_ath_rx_edma.h>
+#ifdef ATH_DEBUG_ALQ
+#include <dev/ath/if_ath_alq.h>
+#endif
+
/*
* some general macros
*/
@@ -357,7 +361,12 @@ ath_edma_recv_proc_queue(struct ath_softc *sc, HAL_RX_QUEUE qtype,
#ifdef ATH_DEBUG
if (sc->sc_debug & ATH_DEBUG_RECV_DESC)
ath_printrxbuf(sc, bf, 0, bf->bf_rxstatus == HAL_OK);
-#endif
+#endif /* ATH_DEBUG */
+#ifdef ATH_DEBUG_ALQ
+ if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_RXSTATUS))
+ if_ath_alq_post(&sc->sc_alq, ATH_ALQ_EDMA_RXSTATUS,
+ sc->sc_rx_statuslen, (char *) ds);
+#endif /* ATH_DEBUG */
if (bf->bf_rxstatus == HAL_EINPROGRESS)
break;
diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c
index 9c9ce52..f293f52 100644
--- a/sys/dev/ath/if_ath_sysctl.c
+++ b/sys/dev/ath/if_ath_sysctl.c
@@ -501,6 +501,57 @@ ath_sysctl_forcebstuck(SYSCTL_HANDLER_ARGS)
return 0;
}
+
+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);
+}
+
+#ifdef ATH_DEBUG
+/*
+ * 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
+
void
ath_sysctlattach(struct ath_softc *sc)
{
@@ -655,6 +706,10 @@ ath_sysctlattach(struct ath_softc *sc)
ath_sysctl_setcca, "I", "enable CCA control");
}
#endif
+
+#ifdef ATH_DEBUG
+ ath_sysctl_alq_attach(sc);
+#endif
}
static int
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index cf465c4..e18785e 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -101,6 +101,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/if_ath_tx.h>
#include <dev/ath/if_ath_tx_ht.h>
+#ifdef ATH_DEBUG_ALQ
+#include <dev/ath/if_ath_alq.h>
+#endif
+
/*
* How many retries to perform in software
*/
diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c
index 57e180b..e23c99a 100644
--- a/sys/dev/ath/if_ath_tx_edma.c
+++ b/sys/dev/ath/if_ath_tx_edma.c
@@ -117,6 +117,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/if_ath_tx_edma.h>
+#ifdef ATH_DEBUG_ALQ
+#include <dev/ath/if_ath_alq.h>
+#endif
+
/*
* some general macros
*/
@@ -132,6 +136,37 @@ MALLOC_DECLARE(M_ATHDEV);
static void ath_edma_tx_processq(struct ath_softc *sc, int dosched);
+#ifdef ATH_DEBUG_ALQ
+static void
+ath_edma_tx_alq_post(struct ath_softc *sc, struct ath_buf *bf_first)
+{
+ struct ath_buf *bf;
+ int i, n;
+ const char *ds;
+
+ /* XXX we should skip out early if debugging isn't enabled! */
+ bf = bf_first;
+
+ while (bf != NULL) {
+ /* XXX assume nmaps = 4! */
+ /* XXX should ensure bf_nseg > 0! */
+ if (bf->bf_nseg == 0)
+ break;
+ n = ((bf->bf_nseg - 1) / 4) + 1;
+ for (i = 0, ds = (const char *) bf->bf_desc;
+ i < n;
+ i++, ds += sc->sc_tx_desclen) {
+ if_ath_alq_post(&sc->sc_alq,
+ ATH_ALQ_EDMA_TXDESC,
+ 96,
+ ds);
+ }
+
+ bf = bf->bf_next;
+ }
+}
+#endif /* ATH_DEBUG_ALQ */
+
static void
ath_edma_tx_fifo_fill(struct ath_softc *sc, struct ath_txq *txq)
{
@@ -149,7 +184,11 @@ ath_edma_tx_fifo_fill(struct ath_softc *sc, struct ath_txq *txq)
#ifdef ATH_DEBUG
if (sc->sc_debug & ATH_DEBUG_XMIT_DESC)
ath_printtxbuf(sc, bf, txq->axq_qnum, i, 0);
-#endif
+#endif/* ATH_DEBUG */
+#ifdef ATH_DEBUG_ALQ
+ if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_TXDESC))
+ ath_edma_tx_alq_post(sc, bf);
+#endif /* ATH_DEBUG_ALQ */
txq->axq_fifo_depth++;
i++;
}
@@ -163,10 +202,6 @@ ath_edma_tx_fifo_fill(struct ath_softc *sc, struct ath_txq *txq)
*
* This should only be called as part of the chip reset path, as it
* assumes the FIFO is currently empty.
- *
- * TODO: verify that a cold/warm reset does clear the TX FIFO, so
- * writing in a partially-filled FIFO will not cause double-entries
- * to appear.
*/
static void
ath_edma_dma_restart(struct ath_softc *sc, struct ath_txq *txq)
@@ -222,7 +257,11 @@ ath_edma_xmit_handoff_hw(struct ath_softc *sc, struct ath_txq *txq,
#ifdef ATH_DEBUG
if (sc->sc_debug & ATH_DEBUG_XMIT_DESC)
ath_printtxbuf(sc, bf, txq->axq_qnum, 0, 0);
-#endif /* ATH_DEBUG */
+#endif /* ATH_DEBUG */
+#ifdef ATH_DEBUG_ALQ
+ if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_TXDESC))
+ ath_edma_tx_alq_post(sc, bf);
+#endif /* ATH_DEBUG_ALQ */
ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
txq->axq_fifo_depth++;
ath_hal_txstart(ah, txq->axq_qnum);
@@ -368,7 +407,6 @@ ath_edma_dma_txsetup(struct ath_softc *sc)
ath_edma_setup_txfifo(sc, i);
}
-
return (0);
}
@@ -489,6 +527,13 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched)
continue;
}
+#ifdef ATH_DEBUG_ALQ
+ if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS))
+ if_ath_alq_post(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS,
+ sc->sc_tx_statuslen,
+ (char *) txstatus);
+#endif /* ATH_DEBUG_ALQ */
+
/*
* At this point we have a valid status descriptor.
* The QID and descriptor ID (which currently isn't set)
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 974db28..dd805b0 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -42,6 +42,9 @@
#include <net80211/ieee80211_radiotap.h>
#include <dev/ath/if_athioctl.h>
#include <dev/ath/if_athrate.h>
+#ifdef ATH_DEBUG_ALQ
+#include <dev/ath/if_ath_alq.h>
+#endif
#define ATH_TIMEOUT 1000
@@ -770,6 +773,11 @@ struct ath_softc {
int sc_dodfs; /* Whether to enable DFS rx filter bits */
struct task sc_dfstask; /* DFS processing task */
+ /* ALQ */
+#ifdef ATH_DEBUG
+ struct if_ath_alq sc_alq;
+#endif
+
/* TX AMPDU handling */
int (*sc_addba_request)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *, int, int, int);
OpenPOWER on IntegriCloud