* Add some more debugging to if_arge

* Make doubly sure that IFF_DRV_OACTIVE is set if the hardware TX queue is full
This commit is contained in:
Adrian Chadd 2011-04-05 06:33:35 +00:00
parent ef2732b2ee
commit 85df7b525a
2 changed files with 33 additions and 2 deletions

View File

@ -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 mbuf **m_head)
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);

View File

@ -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;
};