PCI-E VT6130 NIC (if_vge) hang system with gigabit link
Andrey Smagin
samspeed at mail.ru
Tue Nov 22 06:59:18 UTC 2011
Hi! Some days back I put card in Win7 machine.
Win7 hang own network subsystem if connected to gigabit switch.
I tried last night your patches. Now when put in gigabit switch no hangs or errors,
but link (autodetect) 100mbit/s and work good.
I think I bought buggy network cards :((.
Index: sys/dev/mii/ip1000phy.c
===================================================================
--- sys/dev/mii/ip1000phy.c (revision 227501)
+++ sys/dev/mii/ip1000phy.c (working copy)
@@ -324,7 +324,6 @@
PHY_WRITE(sc, IP1000PHY_MII_ANAR, reg | IP1000PHY_ANAR_CSMA);
reg = IP1000PHY_1000CR_1000T | IP1000PHY_1000CR_1000T_FDX;
- reg |= IP1000PHY_1000CR_MASTER;
PHY_WRITE(sc, IP1000PHY_MII_1000CR, reg);
PHY_WRITE(sc, IP1000PHY_MII_BMCR, (IP1000PHY_BMCR_FDX |
IP1000PHY_BMCR_AUTOEN | IP1000PHY_BMCR_STARTNEG));
Index: sys/dev/vge/if_vge.c
===================================================================
--- sys/dev/vge/if_vge.c (revision 227501)
+++ sys/dev/vge/if_vge.c (working copy)
@@ -173,6 +173,7 @@
static void vge_freebufs(struct vge_softc *);
static void vge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
static int vge_ifmedia_upd(struct ifnet *);
+static int vge_ifmedia_upd_locked(struct vge_softc *);
static void vge_init(void *);
static void vge_init_locked(struct vge_softc *);
static void vge_intr(void *);
@@ -180,7 +181,6 @@
static int vge_ioctl(struct ifnet *, u_long, caddr_t);
static void vge_link_statchg(void *);
static int vge_miibus_readreg(device_t, int, int);
-static void vge_miibus_statchg(device_t);
static int vge_miibus_writereg(device_t, int, int, int);
static void vge_miipoll_start(struct vge_softc *);
static void vge_miipoll_stop(struct vge_softc *);
@@ -190,6 +190,7 @@
static int vge_rx_list_init(struct vge_softc *);
static int vge_rxeof(struct vge_softc *, int);
static void vge_rxfilter(struct vge_softc *);
+static void vge_setmedia(struct vge_softc *);
static void vge_setvlan(struct vge_softc *);
static void vge_setwol(struct vge_softc *);
static void vge_start(struct ifnet *);
@@ -218,7 +219,6 @@
/* MII interface */
DEVMETHOD(miibus_readreg, vge_miibus_readreg),
DEVMETHOD(miibus_writereg, vge_miibus_writereg),
- DEVMETHOD(miibus_statchg, vge_miibus_statchg),
{ 0, 0 }
};
@@ -1099,10 +1099,11 @@
goto fail;
}
+ vge_miipoll_start(sc);
/* Do MII setup */
error = mii_attach(dev, &sc->vge_miibus, ifp, vge_ifmedia_upd,
vge_ifmedia_sts, BMSR_DEFCAPMASK, sc->vge_phyaddr, MII_OFFSET_ANY,
- 0);
+ MIIF_DOPAUSE);
if (error != 0) {
device_printf(dev, "attaching PHYs failed\n");
goto fail;
@@ -1660,30 +1661,41 @@
{
struct vge_softc *sc;
struct ifnet *ifp;
- struct mii_data *mii;
+ uint8_t physts;
sc = xsc;
ifp = sc->vge_ifp;
VGE_LOCK_ASSERT(sc);
- mii = device_get_softc(sc->vge_miibus);
- mii_pollstat(mii);
- if ((sc->vge_flags & VGE_FLAG_LINK) != 0) {
- if (!(mii->mii_media_status & IFM_ACTIVE)) {
+ physts = CSR_READ_1(sc, VGE_PHYSTS0);
+ if ((physts & VGE_PHYSTS_RESETSTS) == 0) {
+ if ((physts & VGE_PHYSTS_LINK) == 0) {
sc->vge_flags &= ~VGE_FLAG_LINK;
if_link_state_change(sc->vge_ifp,
LINK_STATE_DOWN);
- }
- } else {
- if (mii->mii_media_status & IFM_ACTIVE &&
- IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
+ } else {
sc->vge_flags |= VGE_FLAG_LINK;
if_link_state_change(sc->vge_ifp,
LINK_STATE_UP);
+ CSR_WRITE_1(sc, VGE_CRC2, VGE_CR2_FDX_TXFLOWCTL_ENABLE |
+ VGE_CR2_FDX_RXFLOWCTL_ENABLE);
+ if ((physts & VGE_PHYSTS_FDX) != 0) {
+ if ((physts & VGE_PHYSTS_TXFLOWCAP) != 0)
+ CSR_WRITE_1(sc, VGE_CRS2,
+ VGE_CR2_FDX_TXFLOWCTL_ENABLE);
+ if ((physts & VGE_PHYSTS_RXFLOWCAP) != 0)
+ CSR_WRITE_1(sc, VGE_CRS2,
+ VGE_CR2_FDX_RXFLOWCTL_ENABLE);
+ }
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
vge_start_locked(ifp);
}
}
+ /*
+ * Restart MII auto-polling because link state change interrupt
+ * will disable it.
+ */
+ vge_miipoll_start(sc);
}
#ifdef DEVICE_POLLING
@@ -2028,6 +2040,7 @@
*/
vge_stop(sc);
vge_reset(sc);
+ vge_miipoll_start(sc);
/*
* Initialize the RX and TX descriptors and mbufs.
@@ -2099,10 +2112,17 @@
vge_rxfilter(sc);
vge_setvlan(sc);
- /* Enable flow control */
+ /* Initialize pause timer. */
+ CSR_WRITE_2(sc, VGE_TX_PAUSE_TIMER, 0xFFFF);
+ /*
+ * Initialize flow control parameters.
+ * TX XON high threshold : 48
+ * TX pause low threshold : 24
+ * Disable hald-duplex flow control
+ */
+ CSR_WRITE_1(sc, VGE_CRC2, 0xFF);
+ CSR_WRITE_1(sc, VGE_CRS2, VGE_CR2_XON_ENABLE | 0x0B);
- CSR_WRITE_1(sc, VGE_CRS2, 0x8B);
-
/* Enable jumbo frame reception (if desired) */
/* Start the MAC. */
@@ -2129,7 +2149,7 @@
CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK);
sc->vge_flags &= ~VGE_FLAG_LINK;
- mii_mediachg(mii);
+ vge_ifmedia_upd_locked(sc);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -2143,14 +2163,28 @@
vge_ifmedia_upd(struct ifnet *ifp)
{
struct vge_softc *sc;
- struct mii_data *mii;
int error;
sc = ifp->if_softc;
VGE_LOCK(sc);
+ error = vge_ifmedia_upd_locked(sc);
+ VGE_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+vge_ifmedia_upd_locked(struct vge_softc *sc)
+{
+ struct mii_data *mii;
+ struct mii_softc *miisc;
+ int error;
+
mii = device_get_softc(sc->vge_miibus);
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ PHY_RESET(miisc);
+ vge_setmedia(sc);
error = mii_mediachg(mii);
- VGE_UNLOCK(sc);
return (error);
}
@@ -2179,13 +2213,11 @@
}
static void
-vge_miibus_statchg(device_t dev)
+vge_setmedia(struct vge_softc *sc)
{
- struct vge_softc *sc;
struct mii_data *mii;
struct ifmedia_entry *ife;
- sc = device_get_softc(dev);
mii = device_get_softc(sc->vge_miibus);
ife = mii->mii_media.ifm_cur;
@@ -2219,7 +2251,7 @@
}
break;
default:
- device_printf(dev, "unknown media type: %x\n",
+ device_printf(sc->vge_dev, "unknown media type: %x\n",
IFM_SUBTYPE(ife->ifm_media));
break;
}
@@ -2772,6 +2804,9 @@
break;
}
}
+ /* Clear forced MAC speed/duplex configuration. */
+ CSR_CLRBIT_1(sc, VGE_DIAGCTL, VGE_DIAGCTL_MACFORCE);
+ CSR_CLRBIT_1(sc, VGE_DIAGCTL, VGE_DIAGCTL_FDXFORCE);
vge_miibus_writereg(sc->vge_dev, sc->vge_phyaddr, MII_100T2CR, 0);
vge_miibus_writereg(sc->vge_dev, sc->vge_phyaddr, MII_ANAR,
ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA);
More information about the freebsd-net
mailing list