svn commit: r194421 - in stable/7/sys: . contrib/pf dev/msk

Pyun YongHyeon yongari at FreeBSD.org
Thu Jun 18 05:29:31 UTC 2009


Author: yongari
Date: Thu Jun 18 05:29:30 2009
New Revision: 194421
URL: http://svn.freebsd.org/changeset/base/194421

Log:
  MFC r192735-192740,192742:
    Add workaround for Yukon FE+ A0. This controller is known to have
    severe silicon bugs that can't handle VLAN hardware tagging as well
    as status LE writeback bug. The status LE writeback bug is so
    critical we can't trust status word of received frame. To accept
    frames on Yukon FE+ A0 msk(4) just do minimal check for received
    frames and pass them to upper stack. This means msk(4) can pass
    corrupted frames to upper layer. You have been warned!
    Also I supposed RX_GMF_FL_THR to be 32bits register but Linux
    driver treated it as 16bit register so follow their leads. At least
    this does not seem to break msk(4) on Yukon FE+.
  
    Tested by:    bz, Tanguy Bouzeloc ( the.zauron <> gmail dot com )
                  Bruce Cran ( bruce <> cran dot org dot uk )
                  Michael Reifenberger ( mike <> reifenberger dot com )
                  Stephen Montgomery-Smith ( stephen <> missouri dot edu )
  
  r192736:
    Add device ids for Yukon FE+(88E8040, 88E8040T, 88E8048 and 88E8070).
  
  r192737:
    If interface is not UP, don't return media status.
  
  r192738:
    Don't reinitialize controller when interface is already running.
  
  r192739:
    Be consistent with other capability checking.
  
  r192740:
    Simplify SIOCSIFFLAGS handler.
  
  r192742:
    Correct controller description for 88E8035, 88E8036, 88E8038 and
    88E8039. These are fast ethernet controllers.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/msk/if_msk.c
  stable/7/sys/dev/msk/if_mskreg.h

Modified: stable/7/sys/dev/msk/if_msk.c
==============================================================================
--- stable/7/sys/dev/msk/if_msk.c	Thu Jun 18 05:20:02 2009	(r194420)
+++ stable/7/sys/dev/msk/if_msk.c	Thu Jun 18 05:29:30 2009	(r194421)
@@ -190,13 +190,21 @@ static struct msk_product {
 	{ VENDORID_MARVELL, DEVICEID_MRVL_8062X,
 	    "Marvell Yukon 88E8062 SX/LX Gigabit Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_8035,
-	    "Marvell Yukon 88E8035 Gigabit Ethernet" },
+	    "Marvell Yukon 88E8035 Fast Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_8036,
-	    "Marvell Yukon 88E8036 Gigabit Ethernet" },
+	    "Marvell Yukon 88E8036 Fast Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_8038,
-	    "Marvell Yukon 88E8038 Gigabit Ethernet" },
+	    "Marvell Yukon 88E8038 Fast Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_8039,
-	    "Marvell Yukon 88E8039 Gigabit Ethernet" },
+	    "Marvell Yukon 88E8039 Fast Ethernet" },
+	{ VENDORID_MARVELL, DEVICEID_MRVL_8040,
+	    "Marvell Yukon 88E8040 Fast Ethernet" },
+	{ VENDORID_MARVELL, DEVICEID_MRVL_8040T,
+	    "Marvell Yukon 88E8040T Fast Ethernet" },
+	{ VENDORID_MARVELL, DEVICEID_MRVL_8048,
+	    "Marvell Yukon 88E8048 Fast Ethernet" },
+	{ VENDORID_MARVELL, DEVICEID_MRVL_8070,
+	    "Marvell Yukon 88E8070 Fast Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_4361,
 	    "Marvell Yukon 88E8050 Gigabit Ethernet" },
 	{ VENDORID_MARVELL, DEVICEID_MRVL_4360,
@@ -896,6 +904,10 @@ msk_mediastatus(struct ifnet *ifp, struc
 
 	sc_if = ifp->if_softc;
 	MSK_IF_LOCK(sc_if);
+	if ((ifp->if_flags & IFF_UP) == 0) {
+		MSK_IF_UNLOCK(sc_if);
+		return;
+	}
 	mii = device_get_softc(sc_if->msk_miibus);
 
 	mii_pollstat(mii);
@@ -945,18 +957,14 @@ msk_ioctl(struct ifnet *ifp, u_long comm
 	case SIOCSIFFLAGS:
 		MSK_IF_LOCK(sc_if);
 		if ((ifp->if_flags & IFF_UP) != 0) {
-			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
-				if (((ifp->if_flags ^ sc_if->msk_if_flags)
-				    & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
-					msk_rxfilter(sc_if);
-			} else {
-				if ((sc_if->msk_flags & MSK_FLAG_DETACH) == 0)
-					msk_init_locked(sc_if);
-			}
-		} else {
-			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
-				msk_stop(sc_if);
-		}
+			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
+			    ((ifp->if_flags ^ sc_if->msk_if_flags) &
+			    (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+				msk_rxfilter(sc_if);
+			else if ((sc_if->msk_flags & MSK_FLAG_DETACH) == 0)
+				msk_init_locked(sc_if);
+		} else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+			msk_stop(sc_if);
 		sc_if->msk_if_flags = ifp->if_flags;
 		MSK_IF_UNLOCK(sc_if);
 		break;
@@ -975,23 +983,24 @@ msk_ioctl(struct ifnet *ifp, u_long comm
 	case SIOCSIFCAP:
 		MSK_IF_LOCK(sc_if);
 		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
-		if ((mask & IFCAP_TXCSUM) != 0) {
+		if ((mask & IFCAP_TXCSUM) != 0 &&
+		    (IFCAP_TXCSUM & ifp->if_capabilities) != 0) {
 			ifp->if_capenable ^= IFCAP_TXCSUM;
-			if ((IFCAP_TXCSUM & ifp->if_capenable) != 0 &&
-			    (IFCAP_TXCSUM & ifp->if_capabilities) != 0)
+			if ((IFCAP_TXCSUM & ifp->if_capenable) != 0)
 				ifp->if_hwassist |= MSK_CSUM_FEATURES;
 			else
 				ifp->if_hwassist &= ~MSK_CSUM_FEATURES;
 		}
-		if ((mask & IFCAP_VLAN_HWTAGGING) != 0) {
+		if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
+		    (IFCAP_VLAN_HWTAGGING & ifp->if_capabilities) != 0) {
 			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
 			msk_setvlan(sc_if, ifp);
 		}
 
-		if ((mask & IFCAP_TSO4) != 0) {
+		if ((mask & IFCAP_TSO4) != 0 &&
+		    (IFCAP_TSO4 & ifp->if_capabilities) != 0) {
 			ifp->if_capenable ^= IFCAP_TSO4;
-			if ((IFCAP_TSO4 & ifp->if_capenable) != 0 &&
-			    (IFCAP_TSO4 & ifp->if_capabilities) != 0)
+			if ((IFCAP_TSO4 & ifp->if_capenable) != 0)
 				ifp->if_hwassist |= CSUM_TSO;
 			else
 				ifp->if_hwassist &= ~CSUM_TSO;
@@ -1493,14 +1502,17 @@ msk_attach(device_t dev)
 	ether_ifattach(ifp, eaddr);
 	MSK_IF_LOCK(sc_if);
 
-	/*
-	 * VLAN capability setup 
-	 * Due to Tx checksum offload hardware bugs, msk(4) manually
-	 * computes checksum for short frames. For VLAN tagged frames
-	 * this workaround does not work so disable checksum offload
-	 * for VLAN interface.
-	 */
-	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
+	/* VLAN capability setup */
+	ifp->if_capabilities |= IFCAP_VLAN_MTU;
+	if ((sc_if->msk_flags & MSK_FLAG_NOHWVLAN) == 0) {
+		/*
+		 * Due to Tx checksum offload hardware bugs, msk(4) manually
+		 * computes checksum for short frames. For VLAN tagged frames
+		 * this workaround does not work so disable checksum offload
+		 * for VLAN interface.
+		 */
+        	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
+	}
 	ifp->if_capenable = ifp->if_capabilities;
 
 	/*
@@ -1646,6 +1658,19 @@ mskc_attach(device_t dev)
 	case CHIP_ID_YUKON_FE_P:
 		sc->msk_clock = 50;	/* 50 Mhz */
 		sc->msk_pflags |= MSK_FLAG_FASTETHER | MSK_FLAG_DESCV2;
+		if (sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) {
+			/*
+			 * XXX
+			 * FE+ A0 has status LE writeback bug so msk(4)
+			 * does not rely on status word of received frame
+			 * in msk_rxeof() which in turn disables all
+			 * hardware assistance bits reported by the status
+			 * word as well as validity of the recevied frame.
+			 * Just pass received frames to upper stack with
+			 * minimal test and let upper stack handle them.
+			 */
+			sc->msk_pflags |= MSK_FLAG_NOHWVLAN | MSK_FLAG_NORXCHK;
+		}
 		break;
 	case CHIP_ID_YUKON_XL:
 		sc->msk_clock = 156;	/* 156 Mhz */
@@ -2735,6 +2760,7 @@ msk_watchdog(struct msk_if_softc *sc_if)
 			if_printf(sc_if->msk_ifp, "watchdog timeout "
 			   "(missed link)\n");
 		ifp->if_oerrors++;
+		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 		msk_init_locked(sc_if);
 		return;
 	}
@@ -2759,6 +2785,7 @@ msk_watchdog(struct msk_if_softc *sc_if)
 
 	if_printf(ifp, "watchdog timeout\n");
 	ifp->if_oerrors++;
+	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 	msk_init_locked(sc_if);
 	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
 		taskqueue_enqueue(taskqueue_fast, &sc_if->msk_tx_task);
@@ -2837,8 +2864,11 @@ mskc_resume(device_t dev)
 	mskc_reset(sc);
 	for (i = 0; i < sc->msk_num_port; i++) {
 		if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL &&
-		    ((sc->msk_if[i]->msk_ifp->if_flags & IFF_UP) != 0))
+		    ((sc->msk_if[i]->msk_ifp->if_flags & IFF_UP) != 0)) {
+			sc->msk_if[i]->msk_ifp->if_drv_flags &=
+			    ~IFF_DRV_RUNNING;
 			msk_init_locked(sc->msk_if[i]);
+		}
 	}
 	sc->msk_pflags &= ~MSK_FLAG_SUSPEND;
 
@@ -2882,7 +2912,18 @@ msk_rxeof(struct msk_if_softc *sc_if, ui
 		if ((status & GMR_FS_VLAN) != 0 &&
 		    (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0)
 			rxlen -= ETHER_VLAN_ENCAP_LEN;
-		if (len > sc_if->msk_framesize ||
+		if ((sc_if->msk_flags & MSK_FLAG_NORXCHK) != 0) {
+			/*
+			 * For controllers that returns bogus status code
+			 * just do minimal check and let upper stack
+			 * handle this frame.
+			 */
+			if (len > MSK_MAX_FRAMELEN || len < ETHER_HDR_LEN) {
+				ifp->if_ierrors++;
+				msk_discard_rxbuf(sc_if, cons);
+				break;
+			}
+		} else if (len > sc_if->msk_framesize ||
 		    ((status & GMR_FS_ANY_ERR) != 0) ||
 		    ((status & GMR_FS_RX_OK) == 0) || (rxlen != len)) {
 			/* Don't count flow-control packet as errors. */
@@ -3527,6 +3568,9 @@ msk_init_locked(struct msk_if_softc *sc_
 	sc = sc_if->msk_softc;
 	mii = device_get_softc(sc_if->msk_miibus);
 
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+		return;
+
 	error = 0;
 	/* Cancel pending I/O and free all Rx/Tx buffers. */
 	msk_stop(sc_if);
@@ -3613,8 +3657,12 @@ msk_init_locked(struct msk_if_softc *sc_
 	 * Set Rx FIFO flush threshold to 64 bytes + 1 FIFO word
 	 * due to hardware hang on receipt of pause frames.
 	 */
-	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_THR),
-	    RX_GMF_FL_THR_DEF + 1);
+	reg = RX_GMF_FL_THR_DEF + 1;
+	/* Another magic for Yukon FE+ - From Linux. */
+	if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P &&
+	    sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0)
+		reg = 0x178;
+	CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_THR), reg);
 
 	/* Configure Tx MAC FIFO. */
 	CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_RST_SET);
@@ -3646,6 +3694,14 @@ msk_init_locked(struct msk_if_softc *sc_
 		}
 	}
 
+ 	if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P &&
+ 	    sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) {
+ 		/* Disable dynamic watermark - from Linux. */
+ 		reg = CSR_READ_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_EA));
+ 		reg &= ~0x03;
+ 		CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_EA), reg);
+ 	}
+
 	/*
 	 * Disable Force Sync bit and Alloc bit in Tx RAM interface
 	 * arbiter as we don't use Sync Tx queue.

Modified: stable/7/sys/dev/msk/if_mskreg.h
==============================================================================
--- stable/7/sys/dev/msk/if_mskreg.h	Thu Jun 18 05:20:02 2009	(r194420)
+++ stable/7/sys/dev/msk/if_mskreg.h	Thu Jun 18 05:29:30 2009	(r194421)
@@ -130,12 +130,16 @@
 #define DEVICEID_MRVL_8035	0x4350
 #define DEVICEID_MRVL_8036	0x4351
 #define DEVICEID_MRVL_8038	0x4352
-#define DEVICEID_MRVL_8039	0X4353
+#define DEVICEID_MRVL_8039	0x4353
+#define DEVICEID_MRVL_8040	0x4354
+#define DEVICEID_MRVL_8040T	0x4355
+#define DEVICEID_MRVL_8048	0x435A
 #define DEVICEID_MRVL_4360	0x4360
 #define DEVICEID_MRVL_4361	0x4361
 #define DEVICEID_MRVL_4362	0x4362
 #define DEVICEID_MRVL_4363	0x4363
 #define DEVICEID_MRVL_4364	0x4364
+#define DEVICEID_MRVL_8070	0x4365
 #define DEVICEID_MRVL_436A	0x436A
 
 /*
@@ -2396,6 +2400,8 @@ struct msk_if_softc {
 #define	MSK_FLAG_JUMBO_NOCSUM	0x0010
 #define	MSK_FLAG_RAMBUF		0x0020
 #define	MSK_FLAG_DESCV2		0x0040
+#define	MSK_FLAG_NOHWVLAN	0x0080
+#define	MSK_FLAG_NORXCHK	0x0100
 #define	MSK_FLAG_SUSPEND	0x2000
 #define	MSK_FLAG_DETACH		0x4000
 #define	MSK_FLAG_LINK		0x8000


More information about the svn-src-all mailing list