Index: if_nfe.c =================================================================== RCS file: /home/ncvs/src/sys/dev/nfe/if_nfe.c,v retrieving revision 1.21.2.4 diff -u -p -r1.21.2.4 if_nfe.c --- if_nfe.c 18 Mar 2008 00:42:26 -0000 1.21.2.4 +++ if_nfe.c 26 Apr 2008 16:46:04 -0000 @@ -1050,15 +1050,11 @@ nfe_alloc_rx_ring(struct nfe_softc *sc, void *desc; int i, error, descsize; - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->desc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->desc32; - descsize = sizeof (struct nfe_desc32); - } + desc = ring->desc; + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); - ring->cur = ring->next = 0; + ring->cur = 0; error = bus_dma_tag_create(sc->nfe_parent_tag, NFE_RING_ALIGN, 0, /* alignment, boundary */ @@ -1075,17 +1071,14 @@ nfe_alloc_rx_ring(struct nfe_softc *sc, goto fail; } - /* allocate memory to desc */ + /* allocate memory to desc - XXX do we need a temporary desc ? */ error = bus_dmamem_alloc(ring->rx_desc_tag, &desc, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &ring->rx_desc_map); if (error != 0) { device_printf(sc->nfe_dev, "could not create desc DMA map\n"); goto fail; } - if (sc->nfe_flags & NFE_40BIT_ADDR) - ring->desc64 = desc; - else - ring->desc32 = desc; + ring->desc = desc; /* map desc to device visible address space */ ctx.nfe_busaddr = 0; @@ -1158,15 +1151,11 @@ nfe_alloc_jrx_ring(struct nfe_softc *sc, return; } - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->jdesc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->jdesc32; - descsize = sizeof (struct nfe_desc32); - } + desc = ring->jdesc; + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); - ring->jcur = ring->jnext = 0; + ring->jcur = 0; /* Create DMA tag for jumbo Rx ring. */ error = bus_dma_tag_create(sc->nfe_parent_tag, @@ -1230,10 +1219,7 @@ nfe_alloc_jrx_ring(struct nfe_softc *sc, "could not allocate DMA'able memory for jumbo Rx ring\n"); goto fail; } - if (sc->nfe_flags & NFE_40BIT_ADDR) - ring->jdesc64 = desc; - else - ring->jdesc32 = desc; + ring->jdesc = desc; ctx.nfe_busaddr = 0; error = bus_dmamap_load(ring->jrx_desc_tag, ring->jrx_desc_map, desc, @@ -1323,19 +1309,13 @@ fail: static int nfe_init_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) { - void *desc; size_t descsize; int i; - ring->cur = ring->next = 0; - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->desc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->desc32; - descsize = sizeof (struct nfe_desc32); - } - bzero(desc, descsize * NFE_RX_RING_COUNT); + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); + ring->cur = 0; + bzero(ring->desc, descsize * NFE_RX_RING_COUNT); for (i = 0; i < NFE_RX_RING_COUNT; i++) { if (nfe_newbuf(sc, i) != 0) return (ENOBUFS); @@ -1351,19 +1331,13 @@ nfe_init_rx_ring(struct nfe_softc *sc, s static int nfe_init_jrx_ring(struct nfe_softc *sc, struct nfe_jrx_ring *ring) { - void *desc; size_t descsize; int i; - ring->jcur = ring->jnext = 0; - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->jdesc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->jdesc32; - descsize = sizeof (struct nfe_desc32); - } - bzero(desc, descsize * NFE_RX_RING_COUNT); + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); + ring->jcur = 0; + bzero(ring->jdesc, descsize * NFE_RX_RING_COUNT); for (i = 0; i < NFE_JUMBO_RX_RING_COUNT; i++) { if (nfe_jnewbuf(sc, i) != 0) return (ENOBUFS); @@ -1380,16 +1354,10 @@ static void nfe_free_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) { struct nfe_rx_data *data; - void *desc; int i, descsize; - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->desc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->desc32; - descsize = sizeof (struct nfe_desc32); - } + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); for (i = 0; i < NFE_RX_RING_COUNT; i++) { data = &ring->data[i]; @@ -1413,11 +1381,10 @@ nfe_free_rx_ring(struct nfe_softc *sc, s ring->rx_data_tag = NULL; } - if (desc != NULL) { + if (ring->desc != NULL) { bus_dmamap_unload(ring->rx_desc_tag, ring->rx_desc_map); - bus_dmamem_free(ring->rx_desc_tag, desc, ring->rx_desc_map); - ring->desc64 = NULL; - ring->desc32 = NULL; + bus_dmamem_free(ring->rx_desc_tag, ring->desc, ring->rx_desc_map); + ring->desc = NULL; ring->rx_desc_map = NULL; } if (ring->rx_desc_tag != NULL) { @@ -1432,7 +1399,6 @@ nfe_free_jrx_ring(struct nfe_softc *sc, { struct nfe_jpool_entry *entry; struct nfe_rx_data *data; - void *desc; int i, descsize; if ((sc->nfe_flags & NFE_JUMBO_SUP) == 0) @@ -1454,13 +1420,8 @@ nfe_free_jrx_ring(struct nfe_softc *sc, } NFE_JLIST_UNLOCK(sc); - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->jdesc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->jdesc32; - descsize = sizeof (struct nfe_desc32); - } + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); for (i = 0; i < NFE_JUMBO_RX_RING_COUNT; i++) { data = &ring->jdata[i]; @@ -1484,11 +1445,10 @@ nfe_free_jrx_ring(struct nfe_softc *sc, ring->jrx_data_tag = NULL; } - if (desc != NULL) { + if (ring->jdesc != NULL) { bus_dmamap_unload(ring->jrx_desc_tag, ring->jrx_desc_map); - bus_dmamem_free(ring->jrx_desc_tag, desc, ring->jrx_desc_map); - ring->jdesc64 = NULL; - ring->jdesc32 = NULL; + bus_dmamem_free(ring->jrx_desc_tag, ring->jdesc, ring->jrx_desc_map); + ring->jdesc = NULL; ring->jrx_desc_map = NULL; } /* Destroy jumbo buffer block. */ @@ -1515,13 +1475,9 @@ nfe_alloc_tx_ring(struct nfe_softc *sc, void *desc; int descsize; - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->desc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->desc32; - descsize = sizeof (struct nfe_desc32); - } + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); + desc = ring->desc; ring->queued = 0; ring->cur = ring->next = 0; @@ -1547,10 +1503,7 @@ nfe_alloc_tx_ring(struct nfe_softc *sc, device_printf(sc->nfe_dev, "could not create desc DMA map\n"); goto fail; } - if (sc->nfe_flags & NFE_40BIT_ADDR) - ring->desc64 = desc; - else - ring->desc32 = desc; + ring->desc = desc; ctx.nfe_busaddr = 0; error = bus_dmamap_load(ring->tx_desc_tag, ring->tx_desc_map, desc, @@ -1595,20 +1548,14 @@ fail: static void nfe_init_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) { - void *desc; size_t descsize; + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); sc->nfe_force_tx = 0; ring->queued = 0; ring->cur = ring->next = 0; - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->desc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->desc32; - descsize = sizeof (struct nfe_desc32); - } - bzero(desc, descsize * NFE_TX_RING_COUNT); + bzero(ring->desc, descsize * NFE_TX_RING_COUNT); bus_dmamap_sync(ring->tx_desc_tag, ring->tx_desc_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -1619,16 +1566,10 @@ static void nfe_free_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) { struct nfe_tx_data *data; - void *desc; int i, descsize; - if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc = ring->desc64; - descsize = sizeof (struct nfe_desc64); - } else { - desc = ring->desc32; - descsize = sizeof (struct nfe_desc32); - } + descsize = (sc->nfe_flags & NFE_40BIT_ADDR) ? + sizeof (struct nfe_desc64) : sizeof (struct nfe_desc32); for (i = 0; i < NFE_TX_RING_COUNT; i++) { data = &ring->data[i]; @@ -1652,13 +1593,12 @@ nfe_free_tx_ring(struct nfe_softc *sc, s ring->tx_data_tag = NULL; } - if (desc != NULL) { + if (ring->desc != NULL) { bus_dmamap_sync(ring->tx_desc_tag, ring->tx_desc_map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(ring->tx_desc_tag, ring->tx_desc_map); - bus_dmamem_free(ring->tx_desc_tag, desc, ring->tx_desc_map); - ring->desc64 = NULL; - ring->desc32 = NULL; + bus_dmamem_free(ring->tx_desc_tag, ring->desc, ring->tx_desc_map); + ring->desc = NULL; ring->tx_desc_map = NULL; bus_dma_tag_destroy(ring->tx_desc_tag); ring->tx_desc_tag = NULL; @@ -1902,23 +1842,30 @@ nfe_intr(void *arg) return (FILTER_HANDLED); } - static void nfe_int_task(void *arg, int pending) { struct nfe_softc *sc = arg; struct ifnet *ifp = sc->nfe_ifp; uint32_t r; - int domore; NFE_LOCK(sc); - if ((r = NFE_READ(sc, sc->nfe_irq_status)) == 0) { - nfe_enable_intr(sc); - NFE_UNLOCK(sc); - return; /* not for us */ + r = NFE_READ(sc, sc->nfe_irq_status); + if (r == 0 && sc->domore == 0) + goto done; /* not for us, or no more work to do */ + if (r) { + NFE_WRITE(sc, sc->nfe_irq_status, r); + if (r & (NFE_IRQ_RXERR | NFE_IRQ_RX_NOBUF)) { + /* + * Potential stall in the receiver. Record the + * irq_status in sc->needreset and later call + * nfe_intr_locked() to restart the receiver. + */ + sc->nfe_rxringfull++; + sc->needreset = r; + } } - NFE_WRITE(sc, sc->nfe_irq_status, r); DPRINTFN(sc, 5, "nfe_intr: interrupt register %x\n", r); @@ -1935,41 +1882,62 @@ nfe_int_task(void *arg, int pending) DPRINTF(sc, "link state changed\n"); } - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - NFE_UNLOCK(sc); - nfe_enable_intr(sc); - return; - } + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + goto done; - domore = 0; /* check Rx ring */ if (sc->nfe_framesize > MCLBYTES - ETHER_HDR_LEN) - domore = nfe_jrxeof(sc, sc->nfe_process_limit); + sc->domore = nfe_jrxeof(sc, sc->nfe_process_limit); else - domore = nfe_rxeof(sc, sc->nfe_process_limit); + sc->domore = nfe_rxeof(sc, sc->nfe_process_limit); /* check Tx ring */ nfe_txeof(sc); if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) taskqueue_enqueue_fast(sc->nfe_tq, &sc->nfe_tx_task); - NFE_UNLOCK(sc); - - if (domore || (NFE_READ(sc, sc->nfe_irq_status) != 0)) { + if (sc->domore || (NFE_READ(sc, sc->nfe_irq_status) != 0)) { taskqueue_enqueue_fast(sc->nfe_tq, &sc->nfe_int_task); + NFE_UNLOCK(sc); return; } - /* Reenable interrupts. */ +done: + /* Reenable interrupts, check if need reset, and unlock */ nfe_enable_intr(sc); + if (sc->needreset) { + if (1) + printf("%s reset, error 0x%x\n", + __FUNCTION__, sc->needreset); + /* + * We only need to restart the receiver. nfe_init_locked() + * does a lot more than that, but we don't have yet a better + * way to deal with just the receiver. + * In particular, clearing and setting NFE_RX_START + * in NFE_RX_CTL does not restart the receiver correctly. + */ +#if 1 + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* force init_locked */ + nfe_init_locked(sc); +#else + /* The code in this #else block does not help. */ + sc->needreset = 0; + r = NFE_READ(sc, NFE_RX_CTL); + NFE_WRITE(sc, NFE_RX_CTL, r & ~NFE_RX_START); + DELAY(30); + r = NFE_READ(sc, NFE_RX_CTL); + DELAY(30); + NFE_WRITE(sc, NFE_RX_CTL, r | NFE_RX_START); + DELAY(30); +#endif + } + NFE_UNLOCK(sc); } static __inline void nfe_discard_rxbuf(struct nfe_softc *sc, int idx) { - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; struct nfe_rx_data *data; struct mbuf *m; @@ -1977,14 +1945,14 @@ nfe_discard_rxbuf(struct nfe_softc *sc, m = data->m; if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc64 = &sc->rxq.desc64[idx]; + struct nfe_desc64 *desc64 = ((struct nfe_desc64 *)sc->rxq.desc) + idx; /* VLAN packet may have overwritten it. */ desc64->physaddr[0] = htole32(NFE_ADDR_HI(data->paddr)); desc64->physaddr[1] = htole32(NFE_ADDR_LO(data->paddr)); desc64->length = htole16(m->m_len); desc64->flags = htole16(NFE_RX_READY); } else { - desc32 = &sc->rxq.desc32[idx]; + struct nfe_desc32 *desc32 = ((struct nfe_desc32 *)sc->rxq.desc) + idx; desc32->length = htole16(m->m_len); desc32->flags = htole16(NFE_RX_READY); } @@ -1994,8 +1962,6 @@ nfe_discard_rxbuf(struct nfe_softc *sc, static __inline void nfe_discard_jrxbuf(struct nfe_softc *sc, int idx) { - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; struct nfe_rx_data *data; struct mbuf *m; @@ -2003,14 +1969,14 @@ nfe_discard_jrxbuf(struct nfe_softc *sc, m = data->m; if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc64 = &sc->jrxq.jdesc64[idx]; + struct nfe_desc64 *desc64 = ((struct nfe_desc64 *)sc->jrxq.jdesc) + idx; /* VLAN packet may have overwritten it. */ desc64->physaddr[0] = htole32(NFE_ADDR_HI(data->paddr)); desc64->physaddr[1] = htole32(NFE_ADDR_LO(data->paddr)); desc64->length = htole16(m->m_len); desc64->flags = htole16(NFE_RX_READY); } else { - desc32 = &sc->jrxq.jdesc32[idx]; + struct nfe_desc32 *desc32 = ((struct nfe_desc32 *)sc->jrxq.jdesc) + idx; desc32->length = htole16(m->m_len); desc32->flags = htole16(NFE_RX_READY); } @@ -2021,8 +1987,6 @@ static int nfe_newbuf(struct nfe_softc *sc, int idx) { struct nfe_rx_data *data; - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; struct mbuf *m; bus_dma_segment_t segs[1]; bus_dmamap_t map; @@ -2057,13 +2021,13 @@ nfe_newbuf(struct nfe_softc *sc, int idx data->m = m; /* update mapping address in h/w descriptor */ if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc64 = &sc->rxq.desc64[idx]; + struct nfe_desc64 *desc64 = ((struct nfe_desc64 *)sc->rxq.desc) + idx; desc64->physaddr[0] = htole32(NFE_ADDR_HI(segs[0].ds_addr)); desc64->physaddr[1] = htole32(NFE_ADDR_LO(segs[0].ds_addr)); desc64->length = htole16(segs[0].ds_len); desc64->flags = htole16(NFE_RX_READY); } else { - desc32 = &sc->rxq.desc32[idx]; + struct nfe_desc32 *desc32 = ((struct nfe_desc32 *)sc->rxq.desc) + idx; desc32->physaddr = htole32(NFE_ADDR_LO(segs[0].ds_addr)); desc32->length = htole16(segs[0].ds_len); desc32->flags = htole16(NFE_RX_READY); @@ -2077,8 +2041,6 @@ static int nfe_jnewbuf(struct nfe_softc *sc, int idx) { struct nfe_rx_data *data; - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; struct mbuf *m; bus_dma_segment_t segs[1]; bus_dmamap_t map; @@ -2125,13 +2087,13 @@ nfe_jnewbuf(struct nfe_softc *sc, int id data->m = m; /* update mapping address in h/w descriptor */ if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc64 = &sc->jrxq.jdesc64[idx]; + struct nfe_desc64 *desc64 = ((struct nfe_desc64 *)sc->jrxq.jdesc) + idx; desc64->physaddr[0] = htole32(NFE_ADDR_HI(segs[0].ds_addr)); desc64->physaddr[1] = htole32(NFE_ADDR_LO(segs[0].ds_addr)); desc64->length = htole16(segs[0].ds_len); desc64->flags = htole16(NFE_RX_READY); } else { - desc32 = &sc->jrxq.jdesc32[idx]; + struct nfe_desc32 *desc32 = ((struct nfe_desc32 *)sc->jrxq.jdesc) + idx; desc32->physaddr = htole32(NFE_ADDR_LO(segs[0].ds_addr)); desc32->length = htole16(segs[0].ds_len); desc32->flags = htole16(NFE_RX_READY); @@ -2145,33 +2107,34 @@ static int nfe_rxeof(struct nfe_softc *sc, int count) { struct ifnet *ifp = sc->nfe_ifp; - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; struct nfe_rx_data *data; struct mbuf *m; uint16_t flags; int len, prog; - uint32_t vtag = 0; NFE_LOCK_ASSERT(sc); bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, BUS_DMASYNC_POSTREAD); - for (prog = 0;;NFE_INC(sc->rxq.cur, NFE_RX_RING_COUNT), vtag = 0) { + for (prog = 0;;NFE_INC(sc->rxq.cur, NFE_RX_RING_COUNT)) { + uint32_t vtag; + int idx = sc->rxq.cur; + if (count <= 0) break; count--; - - data = &sc->rxq.data[sc->rxq.cur]; + + data = &sc->rxq.data[idx]; if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc64 = &sc->rxq.desc64[sc->rxq.cur]; + struct nfe_desc64 *desc64 = ((struct nfe_desc64 *)sc->rxq.desc) + idx; vtag = le32toh(desc64->physaddr[1]); flags = le16toh(desc64->flags); len = le16toh(desc64->length) & NFE_RX_LEN_MASK; } else { - desc32 = &sc->rxq.desc32[sc->rxq.cur]; + struct nfe_desc32 *desc32 = ((struct nfe_desc32 *)sc->rxq.desc) + idx; + vtag = 0; flags = le16toh(desc32->flags); len = le16toh(desc32->length) & NFE_RX_LEN_MASK; } @@ -2182,7 +2145,7 @@ nfe_rxeof(struct nfe_softc *sc, int coun if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { if (!(flags & NFE_RX_VALID_V1)) { ifp->if_ierrors++; - nfe_discard_rxbuf(sc, sc->rxq.cur); + nfe_discard_rxbuf(sc, idx); continue; } if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { @@ -2192,7 +2155,7 @@ nfe_rxeof(struct nfe_softc *sc, int coun } else { if (!(flags & NFE_RX_VALID_V2)) { ifp->if_ierrors++; - nfe_discard_rxbuf(sc, sc->rxq.cur); + nfe_discard_rxbuf(sc, idx); continue; } @@ -2204,14 +2167,14 @@ nfe_rxeof(struct nfe_softc *sc, int coun if (flags & NFE_RX_ERROR) { ifp->if_ierrors++; - nfe_discard_rxbuf(sc, sc->rxq.cur); + nfe_discard_rxbuf(sc, idx); continue; } m = data->m; - if (nfe_newbuf(sc, sc->rxq.cur) != 0) { + if (nfe_newbuf(sc, idx) != 0) { ifp->if_iqdrops++; - nfe_discard_rxbuf(sc, sc->rxq.cur); + nfe_discard_rxbuf(sc, idx); continue; } @@ -2256,21 +2219,19 @@ static int nfe_jrxeof(struct nfe_softc *sc, int count) { struct ifnet *ifp = sc->nfe_ifp; - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; struct nfe_rx_data *data; struct mbuf *m; uint16_t flags; int len, prog; - uint32_t vtag = 0; NFE_LOCK_ASSERT(sc); bus_dmamap_sync(sc->jrxq.jrx_desc_tag, sc->jrxq.jrx_desc_map, BUS_DMASYNC_POSTREAD); - for (prog = 0;;NFE_INC(sc->jrxq.jcur, NFE_JUMBO_RX_RING_COUNT), - vtag = 0) { + for (prog = 0;;NFE_INC(sc->jrxq.jcur, NFE_JUMBO_RX_RING_COUNT)) { + uint32_t vtag; + int idx = sc->jrxq.jcur; if (count <= 0) break; count--; @@ -2278,12 +2239,13 @@ nfe_jrxeof(struct nfe_softc *sc, int cou data = &sc->jrxq.jdata[sc->jrxq.jcur]; if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc64 = &sc->jrxq.jdesc64[sc->jrxq.jcur]; + struct nfe_desc64 *desc64 = ((struct nfe_desc64 *)sc->jrxq.jdesc) + idx; vtag = le32toh(desc64->physaddr[1]); flags = le16toh(desc64->flags); len = le16toh(desc64->length) & NFE_RX_LEN_MASK; } else { - desc32 = &sc->jrxq.jdesc32[sc->jrxq.jcur]; + struct nfe_desc32 *desc32 = ((struct nfe_desc32 *)sc->jrxq.jdesc) + idx; + vtag = 0; flags = le16toh(desc32->flags); len = le16toh(desc32->length) & NFE_RX_LEN_MASK; } @@ -2294,7 +2256,7 @@ nfe_jrxeof(struct nfe_softc *sc, int cou if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { if (!(flags & NFE_RX_VALID_V1)) { ifp->if_ierrors++; - nfe_discard_jrxbuf(sc, sc->jrxq.jcur); + nfe_discard_jrxbuf(sc, idx); continue; } if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { @@ -2304,7 +2266,7 @@ nfe_jrxeof(struct nfe_softc *sc, int cou } else { if (!(flags & NFE_RX_VALID_V2)) { ifp->if_ierrors++; - nfe_discard_jrxbuf(sc, sc->jrxq.jcur); + nfe_discard_jrxbuf(sc, idx); continue; } @@ -2316,14 +2278,14 @@ nfe_jrxeof(struct nfe_softc *sc, int cou if (flags & NFE_RX_ERROR) { ifp->if_ierrors++; - nfe_discard_jrxbuf(sc, sc->jrxq.jcur); + nfe_discard_jrxbuf(sc, idx); continue; } m = data->m; - if (nfe_jnewbuf(sc, sc->jrxq.jcur) != 0) { + if (nfe_jnewbuf(sc, idx) != 0) { ifp->if_iqdrops++; - nfe_discard_jrxbuf(sc, sc->jrxq.jcur); + nfe_discard_jrxbuf(sc, idx); continue; } @@ -2368,10 +2330,6 @@ static void nfe_txeof(struct nfe_softc *sc) { struct ifnet *ifp = sc->nfe_ifp; - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; - struct nfe_tx_data *data = NULL; - uint16_t flags; int cons, prog; NFE_LOCK_ASSERT(sc); @@ -2382,11 +2340,14 @@ nfe_txeof(struct nfe_softc *sc) prog = 0; for (cons = sc->txq.next; cons != sc->txq.cur; NFE_INC(cons, NFE_TX_RING_COUNT)) { + struct nfe_tx_data *data; + uint16_t flags; + if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc64 = &sc->txq.desc64[cons]; + struct nfe_desc64 *desc64 = ((struct nfe_desc64 *)sc->txq.desc) + cons; flags = le16toh(desc64->flags); } else { - desc32 = &sc->txq.desc32[cons]; + struct nfe_desc32 *desc32 = ((struct nfe_desc32 *)sc->txq.desc) + cons; flags = le16toh(desc32->flags); } @@ -2439,8 +2400,8 @@ nfe_txeof(struct nfe_softc *sc) static int nfe_encap(struct nfe_softc *sc, struct mbuf **m_head) { - struct nfe_desc32 *desc32 = NULL; - struct nfe_desc64 *desc64 = NULL; + struct nfe_desc32 *desc32 = NULL; /* silence compiler, but desc32/64 */ + struct nfe_desc64 *desc64 = NULL; /* are correctly set later. */ bus_dmamap_t map; bus_dma_segment_t segs[NFE_MAX_SCATTER]; int error, i, nsegs, prod, si; @@ -2448,6 +2409,7 @@ nfe_encap(struct nfe_softc *sc, struct m uint16_t cflags, flags; struct mbuf *m; + /* si is the starting index */ prod = si = sc->txq.cur; map = sc->txq.data[prod].tx_data_map; @@ -2501,7 +2463,7 @@ nfe_encap(struct nfe_softc *sc, struct m for (i = 0; i < nsegs; i++) { if (sc->nfe_flags & NFE_40BIT_ADDR) { - desc64 = &sc->txq.desc64[prod]; + desc64 = ((struct nfe_desc64 *)sc->txq.desc) + prod; desc64->physaddr[0] = htole32(NFE_ADDR_HI(segs[i].ds_addr)); desc64->physaddr[1] = @@ -2510,7 +2472,7 @@ nfe_encap(struct nfe_softc *sc, struct m desc64->length = htole16(segs[i].ds_len - 1); desc64->flags = htole16(flags); } else { - desc32 = &sc->txq.desc32[prod]; + desc32 = ((struct nfe_desc32 *)sc->txq.desc) + prod; desc32->physaddr = htole32(NFE_ADDR_LO(segs[i].ds_addr)); desc32->length = htole16(segs[i].ds_len - 1); @@ -2533,7 +2495,7 @@ nfe_encap(struct nfe_softc *sc, struct m */ if (sc->nfe_flags & NFE_40BIT_ADDR) { desc64->flags |= htole16(NFE_TX_LASTFRAG_V2); - desc64 = &sc->txq.desc64[si]; + desc64 = ((struct nfe_desc64 *)sc->txq.desc) + si; if ((m->m_flags & M_VLANTAG) != 0) desc64->vtag = htole32(NFE_TX_VTAG | m->m_pkthdr.ether_vtag); @@ -2556,7 +2518,7 @@ nfe_encap(struct nfe_softc *sc, struct m desc32->flags |= htole16(NFE_TX_LASTFRAG_V2); else desc32->flags |= htole16(NFE_TX_LASTFRAG_V1); - desc32 = &sc->txq.desc32[si]; + desc32 = ((struct nfe_desc32 *)sc->txq.desc) + si; if (tso_segsz != 0) { /* * XXX @@ -2710,6 +2672,32 @@ static void nfe_watchdog(struct ifnet *ifp) { struct nfe_softc *sc = ifp->if_softc; + /* + * Some hardware has stats counters for various events. + * Most if not all of them are 'reset-on'read' so we need to + * accumulate totals in the 'sc'. + * To read and report these numbers (e.g. for debugging purposes) + * change the 'if (0)' to 'if (1)'. + */ + if (0) { + uint32_t a, b, rx, drop, err, ov; + + a = NFE_READ(sc, NFE_RX_CTL); + b = NFE_READ(sc, NFE_RX_STATUS); + rx = NFE_READ(sc, 0x02dc); /* rx receive count (bytes) */ + drop = NFE_READ(sc, 0x02e8); /* rx drop frames */ + err = NFE_READ(sc, 0x02a4); /* rx frame error */ + ov = NFE_READ(sc, 0x02b8); /* rx overflows */ + sc->nfe_rxbytes += rx; + sc->nfe_rxdrop += drop; + sc->nfe_rxerr += err; + sc->nfe_rxoverflow += ov; + + printf("%s rx ctl 0x%x stat 0x%x count %llu/0x%x drop %d err %d ov %d ringfull %d\n", + __FUNCTION__, a, b, sc->nfe_rxbytes, rx, + sc->nfe_rxdrop, sc->nfe_rxerr, + sc->nfe_rxoverflow, sc->nfe_rxringfull); + } if (sc->nfe_watchdog_timer == 0 || --sc->nfe_watchdog_timer) return; @@ -2772,6 +2760,7 @@ nfe_init_locked(void *xsc) nfe_stop(ifp); + sc->needreset = 0; sc->nfe_framesize = ifp->if_mtu + NFE_RX_HEADERS; nfe_init_tx_ring(sc, &sc->txq); @@ -2888,8 +2877,10 @@ nfe_init_locked(void *xsc) nfe_disable_intr(sc); else #endif - nfe_set_intr(sc); - nfe_enable_intr(sc); /* enable interrupts */ + { + nfe_set_intr(sc); + nfe_enable_intr(sc); /* enable interrupts */ + } ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; Index: if_nfevar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/nfe/if_nfevar.h,v retrieving revision 1.5 diff -u -p -r1.5 if_nfevar.h --- if_nfevar.h 24 Jul 2007 01:11:00 -0000 1.5 +++ if_nfevar.h 26 Apr 2008 08:42:47 -0000 @@ -27,8 +27,7 @@ struct nfe_tx_ring { bus_dma_tag_t tx_desc_tag; bus_dmamap_t tx_desc_map; bus_addr_t physaddr; - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; + void *desc; /* either nfe_desc32 or nfe_desc64 */ bus_dma_tag_t tx_data_tag; struct nfe_tx_data data[NFE_TX_RING_COUNT]; int queued; @@ -51,13 +50,11 @@ struct nfe_rx_ring { bus_dma_tag_t rx_desc_tag; bus_dmamap_t rx_desc_map; bus_addr_t physaddr; - struct nfe_desc32 *desc32; - struct nfe_desc64 *desc64; + void *desc; /* either nfe_desc32 or nfe_desc64 */ bus_dma_tag_t rx_data_tag; bus_dmamap_t rx_spare_map; struct nfe_rx_data data[NFE_RX_RING_COUNT]; int cur; - int next; }; struct nfe_jrx_ring { @@ -68,13 +65,11 @@ struct nfe_jrx_ring { void *jpool; caddr_t jslots[NFE_JSLOTS]; bus_addr_t jphysaddr; - struct nfe_desc32 *jdesc32; - struct nfe_desc64 *jdesc64; + void *jdesc; /* either nfe_desc32 or nfe_desc64 */ bus_dma_tag_t jrx_data_tag; bus_dmamap_t jrx_spare_map; struct nfe_rx_data jdata[NFE_JUMBO_RX_RING_COUNT]; int jcur; - int jnext; }; struct nfe_softc { @@ -123,6 +118,16 @@ struct nfe_softc { uint32_t nfe_msi; uint32_t nfe_msix; + uint32_t needreset; /* stall detected in int_task */ + uint32_t domore; /* pending work for int_task */ + + /* stats fields */ + uint32_t nfe_rxringfull; /* how many times the rx ring was full */ + uint64_t nfe_rxbytes; /* received bytes */ + uint32_t nfe_rxdrop; /* dropped packets */ + uint32_t nfe_rxoverflow; /* overflows ? */ + uint32_t nfe_rxerr; /* rx errors */ + struct nfe_tx_ring txq; struct nfe_rx_ring rxq; struct nfe_jrx_ring jrxq;