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 <sys/param.h>
#include <sys/systm.h>
@@ -60,6 +61,10 @@
#include <uvm/uvm_extern.h> /* for PAGE_SIZE */
+#if NRND > 0
+#include <sys/rnd.h>
+#endif
+
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
@@ -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);