Index: if_ste.c =================================================================== RCS file: /cvsroot/src/sys/dev/pci/if_ste.c,v retrieving revision 1.25.2.2 diff -u -r1.25.2.2 if_ste.c --- if_ste.c 22 Oct 2007 20:33:46 -0000 1.25.2.2 +++ if_ste.c 19 Jan 2013 10:22:49 -0000 @@ -45,6 +45,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_ste.c,v 1.25.2.2 2007/10/22 20:33:46 pavel Exp $"); #include "bpfilter.h" +#include "rnd.h" #include #include @@ -60,6 +61,10 @@ #include /* for PAGE_SIZE */ +#if NRND > 0 +#include +#endif + #include #include #include @@ -169,6 +174,15 @@ uint16_t sc_IntEnable; /* prototype IntEnable register */ uint16_t sc_MacCtrl0; /* prototype MacCtrl0 register */ uint8_t sc_ReceiveMode; /* prototype ReceiveMode register */ + +#define STE_USE_DFE580TX_FIX +#ifdef STE_USE_DFE580TX_FIX + int sc_dfe580tx; +#endif + +#if NRND > 0 + rndsource_element_t rnd_source; /* random source */ +#endif }; #define STE_CDTXADDR(sc, x) ((sc)->sc_cddma + STE_CDTXOFF((x))) @@ -331,6 +345,14 @@ printf(": %s\n", sp->ste_name); +#ifdef STE_USE_DFE580TX_FIX + if (PCI_REVISION(pa->pa_class) >= 0x14) { + printf("%s: enable DFE-580TX fix\n", + sc->sc_dev.dv_xname); + sc->sc_dfe580tx = 1; + } +#endif + /* * Map the device. */ @@ -517,6 +539,10 @@ */ if_attach(ifp); ether_ifattach(ifp, enaddr); +#if NRND > 0 + rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, + RND_TYPE_NET, 0); +#endif /* * Make sure the interface is shutdown during reboot. @@ -646,6 +672,7 @@ sc->sc_dev.dv_xname); break; } + MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); if (m0->m_pkthdr.len > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { @@ -760,13 +787,13 @@ if (bus_space_read_4(sc->sc_st, sc->sc_sh, STE_TxDMAListPtr) == 0) { bus_space_write_4(sc->sc_st, sc->sc_sh, - STE_DMACtrl, DC_TxDMAHalt); + STE_DMACtrl, sc->sc_DMACtrl | DC_TxDMAHalt); ste_dmahalt_wait(sc); bus_space_write_4(sc->sc_st, sc->sc_sh, STE_TxDMAListPtr, STE_CDTXADDR(sc, STE_NEXTTX(olasttx))); bus_space_write_4(sc->sc_st, sc->sc_sh, - STE_DMACtrl, DC_TxDMAResume); + STE_DMACtrl, sc->sc_DMACtrl | DC_TxDMAResume); } /* Set a watchdog timer in case the chip flakes out. */ @@ -784,12 +811,17 @@ { struct ste_softc *sc = ifp->if_softc; - printf("%s: device timeout\n", sc->sc_dev.dv_xname); ifp->if_oerrors++; + /* in case interrupts were lost, try processing these */ ste_txintr(sc); ste_rxintr(sc); - (void) ste_init(ifp); + + /* if the timeout condition is still met, reset the chip */ + if (sc->sc_txpending > 0) { + printf("%s: re-init\n", sc->sc_dev.dv_xname); + (void) ste_init(ifp); + } /* Try to get more packets going. */ ste_start(ifp); @@ -850,15 +882,20 @@ uint8_t txstat; int wantinit; - if ((bus_space_read_2(sc->sc_st, sc->sc_sh, STE_IntStatus) & - IS_InterruptStatus) == 0) + isr = bus_space_read_2(sc->sc_st, sc->sc_sh, STE_IntStatus); + if ((isr & IS_InterruptStatus) == 0) return (0); for (wantinit = 0; wantinit == 0;) { - isr = bus_space_read_2(sc->sc_st, sc->sc_sh, STE_IntStatusAck); + bus_space_write_2(sc->sc_st, sc->sc_sh, STE_IntStatus, isr); if ((isr & sc->sc_IntEnable) == 0) break; +#if NRND > 0 + if (RND_ENABLED(&sc->rnd_source)) + rnd_add_uint32(&sc->rnd_source, isr); +#endif + /* Receive interrupts. */ if (isr & IE_RxDMAComplete) ste_rxintr(sc); @@ -921,14 +958,15 @@ sc->sc_dev.dv_xname); wantinit = 1; } + + isr = bus_space_read_2(sc->sc_st, sc->sc_sh, STE_IntStatus); + if ((isr & IS_InterruptStatus) == 0) + break; } if (wantinit) ste_init(ifp); - bus_space_write_2(sc->sc_st, sc->sc_sh, STE_IntEnable, - sc->sc_IntEnable); - /* Try to get more packets going. */ ste_start(ifp); @@ -946,10 +984,15 @@ struct ifnet *ifp = &sc->sc_ethercom.ec_if; struct ste_descsoft *ds; uint32_t control; + uint8_t frameid; int i; ifp->if_flags &= ~IFF_OACTIVE; +#ifdef STE_USE_DFE580TX_FIX + frameid = bus_space_read_1(sc->sc_st, sc->sc_sh, STE_TxFrameId); +#endif + /* * Go through our Tx list and free mbufs for those * frames which have been transmitted. @@ -962,8 +1005,23 @@ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); control = le32toh(sc->sc_txdescs[i].tfd_control); + +#ifdef STE_USE_DFE580TX_FIX + if (sc->sc_dfe580tx) { + uint8_t descid = control >> 2; + if ((descid == frameid) && + (control & TFD_TxDMAComplete) == 0) + break; + if (descid == STE_NEXTTX(frameid)) + break; + } else { + if ((control & TFD_TxDMAComplete) == 0) + break; + } +#else if ((control & TFD_TxDMAComplete) == 0) break; +#endif bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0, ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); @@ -1007,12 +1065,34 @@ if ((status & RFD_RxDMAComplete) == 0) break; + if (status & RFD_RxDMAOverflow) { + printf("%s: RxDMAOverflow frame length = %d\n", + sc->sc_dev.dv_xname, + RFD_RxDMAFrameLen(status)); + } + /* * If the packet had an error, simply recycle the - * buffer. Note, we count the error later in the - * periodic stats update. + * buffer. Note, that these errors are not counted + * in the periodic stats update. */ if (status & RFD_RxFrameError) { + ifp->if_ierrors++; + if (status & RFD_RxFIFOOverrun) + printf("%s: FIFO overflow\n", + sc->sc_dev.dv_xname); + if (status & RFD_RxRuntFrame) + printf("%s: received runt packet\n", + sc->sc_dev.dv_xname); + if (status & RFD_RxAlignmentError) + printf("%s: frame alignment error\n", + sc->sc_dev.dv_xname); + if (status & RFD_RxFCSError) + printf("%s: crc error\n", + sc->sc_dev.dv_xname); + if (status & RFD_RxOversizedFrame) + printf("%s: received giant packet\n", + sc->sc_dev.dv_xname); STE_INIT_RXDESC(sc, i); continue; } @@ -1042,6 +1122,7 @@ MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) goto dropit; + MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); m->m_data += 2; memcpy(mtod(m, caddr_t), mtod(ds->ds_mbuf, caddr_t), len); @@ -1209,11 +1290,13 @@ bus_space_write_4(sc->sc_st, sc->sc_sh, STE_TxDMAListPtr, 0); bus_space_write_2(sc->sc_st, sc->sc_sh, STE_MacCtrl1, MC1_TxEnable); - bus_space_write_4(sc->sc_st, sc->sc_sh, STE_DMACtrl, DC_TxDMAHalt); + bus_space_write_4(sc->sc_st, sc->sc_sh, STE_DMACtrl, + sc->sc_DMACtrl | DC_TxDMAHalt); ste_dmahalt_wait(sc); bus_space_write_4(sc->sc_st, sc->sc_sh, STE_TxDMAListPtr, STE_CDTXADDR(sc, id)); - bus_space_write_4(sc->sc_st, sc->sc_sh, STE_DMACtrl, DC_TxDMAResume); + bus_space_write_4(sc->sc_st, sc->sc_sh, STE_DMACtrl, + sc->sc_DMACtrl | DC_TxDMAResume); } /* @@ -1323,6 +1406,12 @@ bus_space_write_2(st, sh, STE_IntStatus, 0xffff); bus_space_write_2(st, sh, STE_IntEnable, sc->sc_IntEnable); +#ifdef STE_USE_DFE580TX_FIX + /* Fix DFE-580TX packet drop issue */ + if (sc->sc_dfe580tx) + bus_space_write_1(st, sh, STE_DebugCtrl1, 1); +#endif + /* * Start the receive DMA engine. */ @@ -1420,7 +1509,7 @@ * Stop the transmit and receive DMA. */ bus_space_write_4(sc->sc_st, sc->sc_sh, STE_DMACtrl, - DC_RxDMAHalt | DC_TxDMAHalt); + sc->sc_DMACtrl | DC_RxDMAHalt | DC_TxDMAHalt); ste_dmahalt_wait(sc); /* @@ -1496,6 +1585,7 @@ if (m == NULL) return (ENOBUFS); + MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m);