Stability fixes:

- In wb_rxeof(), if the received packet is less than MINCLSIZE bytes,
  copy it to an mbuf chain so as to be more frugal in our use of mbuf
  clusters.

- The Winbond chip, like the ASIX, wants the 'TX interrupt request'
  bit set in the _first_ fragment of a transmitted frame, not the
  last. (At least the Winbond manual states this unambiguously; too
  bad I wasn't paying attention when I read it the first time.)

- Turn off the transmit threshold mechanism (initialize the threshold
  to 0). This effectively puts the chip in 'store and forward' mode
  which seems to cut down on transmit errors a little. It may also
  reduce transmit performace a bit, but I'm willing to do that if it
  means better reliability.
This commit is contained in:
wpaul 1999-01-16 06:25:59 +00:00
parent ba12ad6529
commit 3cd1b4b45f
2 changed files with 47 additions and 24 deletions

View File

@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: if_wb.c,v 1.4 1998/12/14 06:32:56 dillon Exp $
* $Id: if_wb.c,v 1.36 1999/01/16 05:28:52 wpaul Exp $
*/
/*
@ -121,7 +121,7 @@
#ifndef lint
static const char rcsid[] =
"$Id: if_wb.c,v 1.4 1998/12/14 06:32:56 dillon Exp $";
"$Id: if_wb.c,v 1.36 1999/01/16 05:28:52 wpaul Exp $";
#endif
/*
@ -174,8 +174,8 @@ static void wb_shutdown __P((int, void *));
static int wb_ifmedia_upd __P((struct ifnet *));
static void wb_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
static void wb_eeprom_putbyte __P((struct wb_softc *, u_int8_t));
static void wb_eeprom_getword __P((struct wb_softc *, u_int8_t, u_int16_t *));
static void wb_eeprom_putbyte __P((struct wb_softc *, int));
static void wb_eeprom_getword __P((struct wb_softc *, int, u_int16_t *));
static void wb_read_eeprom __P((struct wb_softc *, caddr_t, int,
int, int));
static void wb_mii_sync __P((struct wb_softc *));
@ -183,14 +183,14 @@ static void wb_mii_send __P((struct wb_softc *, u_int32_t, int));
static int wb_mii_readreg __P((struct wb_softc *, struct wb_mii_frame *));
static int wb_mii_writereg __P((struct wb_softc *, struct wb_mii_frame *));
static u_int16_t wb_phy_readreg __P((struct wb_softc *, int));
static void wb_phy_writereg __P((struct wb_softc *, u_int16_t, u_int16_t));
static void wb_phy_writereg __P((struct wb_softc *, int, int));
static void wb_autoneg_xmit __P((struct wb_softc *));
static void wb_autoneg_mii __P((struct wb_softc *, int, int));
static void wb_setmode_mii __P((struct wb_softc *, int));
static void wb_getmode_mii __P((struct wb_softc *));
static void wb_setcfg __P((struct wb_softc *, u_int16_t));
static u_int8_t wb_calchash __P((u_int8_t *));
static void wb_setcfg __P((struct wb_softc *, int));
static u_int8_t wb_calchash __P((caddr_t));
static void wb_setmulti __P((struct wb_softc *));
static void wb_reset __P((struct wb_softc *));
static int wb_list_rx_init __P((struct wb_softc *));
@ -217,7 +217,7 @@ static int wb_list_tx_init __P((struct wb_softc *));
*/
static void wb_eeprom_putbyte(sc, addr)
struct wb_softc *sc;
u_int8_t addr;
int addr;
{
register int d, i;
@ -247,7 +247,7 @@ static void wb_eeprom_putbyte(sc, addr)
*/
static void wb_eeprom_getword(sc, addr, dest)
struct wb_softc *sc;
u_int8_t addr;
int addr;
u_int16_t *dest;
{
register int i;
@ -515,8 +515,8 @@ static u_int16_t wb_phy_readreg(sc, reg)
static void wb_phy_writereg(sc, reg, data)
struct wb_softc *sc;
u_int16_t reg;
u_int16_t data;
int reg;
int data;
{
struct wb_mii_frame frame;
@ -532,7 +532,7 @@ static void wb_phy_writereg(sc, reg, data)
}
static u_int8_t wb_calchash(addr)
u_int8_t *addr;
caddr_t addr;
{
u_int32_t crc, carry;
int i, j;
@ -930,7 +930,7 @@ static void wb_setmode_mii(sc, media)
*/
static void wb_setcfg(sc, bmcr)
struct wb_softc *sc;
u_int16_t bmcr;
int bmcr;
{
int i, restart = 0;
@ -1359,7 +1359,7 @@ static void wb_rxeof(sc)
cur_rx = sc->wb_cdata.wb_rx_head;
sc->wb_cdata.wb_rx_head = cur_rx->wb_nextdesc;
if ((rxstat & WB_RXSTAT_RXERR) || (rxstat & WB_RXSTAT_MIIERR)
if ((rxstat & WB_RXSTAT_MIIERR)
|| WB_RXBYTES(cur_rx->wb_ptr->wb_status) == 0) {
ifp->if_ierrors++;
wb_reset(sc);
@ -1370,8 +1370,15 @@ static void wb_rxeof(sc)
return;
}
if (rxstat & WB_RXSTAT_RXERR) {
ifp->if_ierrors++;
cur_rx->wb_ptr->wb_ctl =
WB_RXCTL_RLINK | (MCLBYTES - 1);
cur_rx->wb_ptr->wb_status = WB_RXSTAT;
continue;
}
/* No errors; receive the packet. */
m = cur_rx->wb_mbuf;
total_len = WB_RXBYTES(cur_rx->wb_ptr->wb_status);
/*
@ -1383,6 +1390,18 @@ static void wb_rxeof(sc)
*/
total_len -= ETHER_CRC_LEN;
if (total_len < MINCLSIZE) {
m = m_devget(mtod(cur_rx->wb_mbuf, char *),
total_len, 0, ifp, NULL);
cur_rx->wb_ptr->wb_ctl =
WB_RXCTL_RLINK | (MCLBYTES - 1);
cur_rx->wb_ptr->wb_status = WB_RXSTAT;
if (m == NULL) {
ifp->if_ierrors++;
continue;
}
} else {
m = cur_rx->wb_mbuf;
/*
* Try to conjure up a new mbuf cluster. If that
* fails, it means we have an out of memory condition and
@ -1390,18 +1409,19 @@ static void wb_rxeof(sc)
* result in a lost packet, but there's little else we
* can do in this situation.
*/
if (wb_newbuf(sc, cur_rx) == ENOBUFS) {
ifp->if_ierrors++;
cur_rx->wb_ptr->wb_ctl =
if (wb_newbuf(sc, cur_rx) == ENOBUFS) {
ifp->if_ierrors++;
cur_rx->wb_ptr->wb_ctl =
WB_RXCTL_RLINK | (MCLBYTES - 1);
cur_rx->wb_ptr->wb_status = WB_RXSTAT;
continue;
cur_rx->wb_ptr->wb_status = WB_RXSTAT;
continue;
}
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = total_len;
}
ifp->if_ipackets++;
eh = mtod(m, struct ether_header *);
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = total_len;
#if NBPFILTER > 0
/*
@ -1561,9 +1581,11 @@ static void wb_intr(arg)
if ((status & WB_ISR_RX_NOBUF) || (status & WB_ISR_RX_ERR)) {
ifp->if_ierrors++;
#ifdef foo
wb_stop(sc);
wb_reset(sc);
wb_init(sc);
#endif
}
if (status & WB_ISR_TX_OK)
@ -1774,6 +1796,7 @@ static void wb_start(ifp)
* once for each packet.
*/
WB_TXCTL(cur_tx) |= WB_TXCTL_FINT;
cur_tx->wb_ptr->wb_frag[0].wb_ctl |= WB_TXCTL_FINT;
sc->wb_cdata.wb_tx_tail = cur_tx;
if (sc->wb_cdata.wb_tx_head == NULL) {

View File

@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: if_wbreg.h,v 1.12 1998/11/29 06:40:50 wpaul Exp $
* $Id: if_wbreg.h,v 1.12 1998/11/29 06:40:50 wpaul Exp wpaul $
*/
/*
@ -160,7 +160,7 @@
*/
#define WB_TXTHRESH(x) ((x >> 5) << 14)
#define WB_TXTHRESH_CHUNK 32
#define WB_TXTHRESH_INIT 72
#define WB_TXTHRESH_INIT 0 /*72*/
/*
* Interrupt mask bits.