svn commit: r220356 - head/sys/mips/atheros
Adrian Chadd
adrian at FreeBSD.org
Tue Apr 5 06:33:36 UTC 2011
Author: adrian
Date: Tue Apr 5 06:33:35 2011
New Revision: 220356
URL: http://svn.freebsd.org/changeset/base/220356
Log:
* Add some more debugging to if_arge
* Make doubly sure that IFF_DRV_OACTIVE is set if the hardware TX queue is full
Modified:
head/sys/mips/atheros/if_arge.c
head/sys/mips/atheros/if_argevar.h
Modified: head/sys/mips/atheros/if_arge.c
==============================================================================
--- head/sys/mips/atheros/if_arge.c Tue Apr 5 05:29:10 2011 (r220355)
+++ head/sys/mips/atheros/if_arge.c Tue Apr 5 06:33:35 2011 (r220356)
@@ -84,7 +84,11 @@ MODULE_DEPEND(arge, miibus, 1, 1, 1);
typedef enum {
ARGE_DBG_MII = 0x00000001,
- ARGE_DBG_INTR = 0x00000002
+ ARGE_DBG_INTR = 0x00000002,
+ ARGE_DBG_TX = 0x00000004,
+ ARGE_DBG_RX = 0x00000008,
+ ARGE_DBG_ERR = 0x00000010,
+ ARGE_DBG_RESET = 0x00000020,
} arge_debug_flags;
#ifdef ARGE_DEBUG
@@ -985,6 +989,7 @@ arge_encap(struct arge_softc *sc, struct
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/* Start transmitting */
+ ARGEDEBUG(sc, ARGE_DBG_TX, "%s: setting DMA_TX_CONTROL_EN\n", __func__);
ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, DMA_TX_CONTROL_EN);
return (0);
}
@@ -1006,16 +1011,32 @@ arge_start_locked(struct ifnet *ifp)
{
struct arge_softc *sc;
struct mbuf *m_head;
- int enq;
+ int enq = 0;
sc = ifp->if_softc;
ARGE_LOCK_ASSERT(sc);
+ ARGEDEBUG(sc, ARGE_DBG_TX, "%s: beginning\n", __func__);
+
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING || sc->arge_link_status == 0 )
return;
+ /*
+ * Before we go any further, check whether we're already full.
+ * The below check errors out immediately if the ring is full
+ * and never gets a chance to set this flag. Although it's
+ * likely never needed, this at least avoids an unexpected
+ * situation.
+ */
+ if (sc->arge_cdata.arge_tx_cnt >= ARGE_TX_RING_COUNT - 2) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ ARGEDEBUG(sc, ARGE_DBG_ERR, "%s: tx_cnt %d >= max %d; setting IFF_DRV_OACTIVE\n",
+ __func__, sc->arge_cdata.arge_tx_cnt, ARGE_TX_RING_COUNT - 2);
+ return;
+ }
+
arge_flush_ddr(sc);
for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
@@ -1043,6 +1064,7 @@ arge_start_locked(struct ifnet *ifp)
*/
ETHER_BPF_MTAP(ifp, m_head);
}
+ ARGEDEBUG(sc, ARGE_DBG_TX, "%s: finished; queued %d packets\n", __func__, enq);
}
static void
@@ -1621,6 +1643,9 @@ arge_tx_locked(struct arge_softc *sc)
cons = sc->arge_cdata.arge_tx_cons;
prod = sc->arge_cdata.arge_tx_prod;
+
+ ARGEDEBUG(sc, ARGE_DBG_TX, "%s: cons=%d, prod=%d\n", __func__, cons, prod);
+
if (cons == prod)
return;
@@ -1771,6 +1796,7 @@ arge_intr(void *arg)
{
struct arge_softc *sc = arg;
uint32_t status;
+ struct ifnet *ifp = sc->arge_ifp;
status = ARGE_READ(sc, AR71XX_DMA_INTR_STATUS);
status |= sc->arge_intr_status;
@@ -1809,6 +1835,7 @@ arge_intr(void *arg)
if ( status & DMA_INTR_RX_OVERFLOW) {
ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_OVERFLOW);
ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, DMA_RX_CONTROL_EN);
+ sc->stats.rx_overflow++;
}
if (status & DMA_INTR_TX_PKT_SENT)
@@ -1819,6 +1846,8 @@ arge_intr(void *arg)
*/
if (status & DMA_INTR_TX_UNDERRUN) {
ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_UNDERRUN);
+ sc->stats.tx_underflow++;
+ ARGEDEBUG(sc, ARGE_DBG_TX, "%s: TX underrun; tx_cnt=%d\n", __func__, sc->arge_cdata.arge_tx_cnt);
if (sc->arge_cdata.arge_tx_cnt > 0 ) {
ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL,
DMA_TX_CONTROL_EN);
Modified: head/sys/mips/atheros/if_argevar.h
==============================================================================
--- head/sys/mips/atheros/if_argevar.h Tue Apr 5 05:29:10 2011 (r220355)
+++ head/sys/mips/atheros/if_argevar.h Tue Apr 5 06:33:35 2011 (r220356)
@@ -154,6 +154,8 @@ struct arge_softc {
struct {
uint32_t tx_pkts_unaligned;
uint32_t tx_pkts_aligned;
+ uint32_t rx_overflow;
+ uint32_t tx_underflow;
} stats;
};
More information about the svn-src-head
mailing list