diff options
author | Marco Pfatschbacher <mpf@cvs.openbsd.org> | 2009-04-28 12:54:32 +0000 |
---|---|---|
committer | Marco Pfatschbacher <mpf@cvs.openbsd.org> | 2009-04-28 12:54:32 +0000 |
commit | caf9d3935f6517a1e524920e1d841d80a4b1cc5a (patch) | |
tree | 9963e96f2173220a3bdbe42bf8318ed9f10ad4a0 /sys | |
parent | cacc01fc73d29b7231e7a8069ffcd331e6f03a1e (diff) |
The TX engine can get stuck if the interface went through a link
state change. Workaround by resetting the chip if necessary.
Also do not try to send packets if our link is down, as this triggers
watchdog timeouts. While there correct the VR_RXSTAT_RX_OK define
(not used yet). Changes inspired from FreeBSDs overhauled vr(4).
Testing, input and OK sthen@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_vr.c | 47 | ||||
-rw-r--r-- | sys/dev/pci/if_vrreg.h | 6 |
2 files changed, 37 insertions, 16 deletions
diff --git a/sys/dev/pci/if_vr.c b/sys/dev/pci/if_vr.c index e8a285961cc..8544c8f45c7 100644 --- a/sys/dev/pci/if_vr.c +++ b/sys/dev/pci/if_vr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vr.c,v 1.81 2009/03/29 21:53:52 sthen Exp $ */ +/* $OpenBSD: if_vr.c,v 1.82 2009/04/28 12:54:31 mpf Exp $ */ /* * Copyright (c) 1997, 1998 @@ -366,20 +366,38 @@ allmulti: void vr_setcfg(struct vr_softc *sc, int media) { - int restart = 0; + int i; - if (CSR_READ_2(sc, VR_COMMAND) & (VR_CMD_TX_ON|VR_CMD_RX_ON)) { - restart = 1; - VR_CLRBIT16(sc, VR_COMMAND, (VR_CMD_TX_ON|VR_CMD_RX_ON)); - } + if (sc->sc_mii.mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(sc->sc_mii.mii_media_active) != IFM_NONE) { + sc->vr_link = 1; - if ((media & IFM_GMASK) == IFM_FDX) - VR_SETBIT16(sc, VR_COMMAND, VR_CMD_FULLDUPLEX); - else - VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_FULLDUPLEX); + if (CSR_READ_2(sc, VR_COMMAND) & (VR_CMD_TX_ON|VR_CMD_RX_ON)) + VR_CLRBIT16(sc, VR_COMMAND, + (VR_CMD_TX_ON|VR_CMD_RX_ON)); + + if ((media & IFM_GMASK) == IFM_FDX) + VR_SETBIT16(sc, VR_COMMAND, VR_CMD_FULLDUPLEX); + else + VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_FULLDUPLEX); - if (restart) VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_ON|VR_CMD_RX_ON); + } else { + sc->vr_link = 0; + VR_CLRBIT16(sc, VR_COMMAND, (VR_CMD_TX_ON|VR_CMD_RX_ON)); + for (i = VR_TIMEOUT; i > 0; i--) { + DELAY(10); + if (!(CSR_READ_2(sc, VR_COMMAND) & + (VR_CMD_TX_ON|VR_CMD_RX_ON))) + break; + } + if (i == 0) { +#ifdef VR_DEBUG + printf("%s: rx shutdown error!\n", sc->sc_dev.dv_xname); +#endif + sc->vr_flags |= VR_F_RESTART; + } + } } void @@ -1132,11 +1150,11 @@ vr_start(struct ifnet *ifp) struct mbuf *m_head; struct vr_chain *cur_tx; - if (ifp->if_flags & IFF_OACTIVE) - return; - sc = ifp->if_softc; + if (ifp->if_flags & IFF_OACTIVE || sc->vr_link == 0) + return; + cur_tx = sc->vr_cdata.vr_tx_prod; while (cur_tx->vr_mbuf == NULL) { IFQ_DEQUEUE(&ifp->if_snd, m_head); @@ -1283,6 +1301,7 @@ vr_init(void *xsc) CSR_WRITE_2(sc, VR_IMR, VR_INTRS); /* Restore state of BMCR */ + sc->vr_link = 0; mii_mediachg(mii); ifp->if_flags |= IFF_RUNNING; diff --git a/sys/dev/pci/if_vrreg.h b/sys/dev/pci/if_vrreg.h index 588b53a5d6b..8be865b4945 100644 --- a/sys/dev/pci/if_vrreg.h +++ b/sys/dev/pci/if_vrreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vrreg.h,v 1.21 2008/07/18 13:38:40 thib Exp $ */ +/* $OpenBSD: if_vrreg.h,v 1.22 2009/04/28 12:54:31 mpf Exp $ */ /* * Copyright (c) 1997, 1998 @@ -350,7 +350,8 @@ struct vr_desc { #define VR_RXSTAT_RX_PHYS 0x00000800 #define VR_RXSTAT_RX_BROAD 0x00001000 #define VR_RXSTAT_RX_MULTI 0x00002000 -#define VR_RXSTAT_RX_OK 0x00004000 +#define VR_RXSTAT_RX_VIDHIT 0x00004000 /* 6105M */ +#define VR_RXSTAT_RX_OK 0x00008000 #define VR_RXSTAT_RXLEN 0x07FF0000 #define VR_RXSTAT_RXLEN_EXT 0x78000000 #define VR_RXSTAT_OWN 0x80000000 @@ -469,6 +470,7 @@ struct vr_softc { bus_dma_segment_t sc_listseg; int sc_if_flags; int sc_rxbufs; + int vr_link; }; #define VR_F_RESTART 0x01 /* Restart unit on next tick */ |