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