svn commit: r216003 - stable/7/sys/dev/fxp

Marius Strobl marius at FreeBSD.org
Sun Nov 28 15:59:46 UTC 2010


Author: marius
Date: Sun Nov 28 15:59:45 2010
New Revision: 216003
URL: http://svn.freebsd.org/changeset/base/216003

Log:
  MFC: r215906
  
  Fix and implement missing parts of flow control support. This also removes
  the dev.fxp.%d.noflow tunable as the same effect can now be achieved with
  ifconfig(8) by setting the flowcontrol media option as desired (besides
  the tunable never having a chance to actually enable flow control support
  so far).
  In joint forces with:	yongari

Modified:
  stable/7/sys/dev/fxp/if_fxp.c
  stable/7/sys/dev/fxp/if_fxpreg.h
  stable/7/sys/dev/fxp/if_fxpvar.h
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/dev/fxp/if_fxp.c
==============================================================================
--- stable/7/sys/dev/fxp/if_fxp.c	Sun Nov 28 15:59:39 2010	(r216002)
+++ stable/7/sys/dev/fxp/if_fxp.c	Sun Nov 28 15:59:45 2010	(r216003)
@@ -224,7 +224,7 @@ static void		fxp_rxcsum(struct fxp_softc
 static void		fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp,
 			    uint8_t statack, int count);
 static void 		fxp_init(void *xsc);
-static void 		fxp_init_body(struct fxp_softc *sc);
+static void 		fxp_init_body(struct fxp_softc *sc, int);
 static void 		fxp_tick(void *xsc);
 static void 		fxp_start(struct ifnet *ifp);
 static void 		fxp_start_body(struct ifnet *ifp);
@@ -261,6 +261,7 @@ static void		fxp_serial_ifmedia_sts(stru
 static int		fxp_miibus_readreg(device_t dev, int phy, int reg);
 static void		fxp_miibus_writereg(device_t dev, int phy, int reg,
 			    int value);
+static void		fxp_miibus_statchg(device_t dev);
 static void		fxp_load_ucode(struct fxp_softc *sc);
 static void		fxp_update_stats(struct fxp_softc *sc);
 static void		fxp_sysctl_node(struct fxp_softc *sc);
@@ -286,6 +287,7 @@ static device_method_t fxp_methods[] = {
 	/* MII interface */
 	DEVMETHOD(miibus_readreg,	fxp_miibus_readreg),
 	DEVMETHOD(miibus_writereg,	fxp_miibus_writereg),
+	DEVMETHOD(miibus_statchg,	fxp_miibus_statchg),
 
 	{ 0, 0 }
 };
@@ -330,8 +332,8 @@ fxp_scb_wait(struct fxp_softc *sc)
 	while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i)
 		DELAY(2);
 	if (i == 0) {
-		flowctl.b[0] = CSR_READ_1(sc, FXP_CSR_FLOWCONTROL);
-		flowctl.b[1] = CSR_READ_1(sc, FXP_CSR_FLOWCONTROL + 1);
+		flowctl.b[0] = CSR_READ_1(sc, FXP_CSR_FC_THRESH);
+		flowctl.b[1] = CSR_READ_1(sc, FXP_CSR_FC_STATUS);
 		device_printf(sc->dev, "SCB timeout: 0x%x 0x%x 0x%x 0x%x\n",
 		    CSR_READ_1(sc, FXP_CSR_SCB_COMMAND),
 		    CSR_READ_1(sc, FXP_CSR_SCB_STATACK),
@@ -427,8 +429,7 @@ fxp_attach(device_t dev)
 	uint32_t val;
 	uint16_t data, myea[ETHER_ADDR_LEN / 2];
 	u_char eaddr[ETHER_ADDR_LEN];
-	int i, pmc, prefer_iomap;
-	int error;
+	int error, flags, i, pmc, prefer_iomap;
 
 	error = 0;
 	sc = device_get_softc(dev);
@@ -808,11 +809,14 @@ fxp_attach(device_t dev)
 		/*
 		 * i82557 wedge when isolating all of their PHYs.
 		 */
+		flags = MIIF_NOISOLATE;
+		if (sc->revision >= FXP_REV_82558_A4)
+			flags |= MIIF_DOPAUSE;
 		error = mii_attach(dev, &sc->miibus, ifp, fxp_ifmedia_upd,
 		    fxp_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY,
-		    MII_OFFSET_ANY, MIIF_NOISOLATE);
+		    MII_OFFSET_ANY, flags);
 		if (error != 0) {
-	                device_printf(dev, "attaching PHYs failed\n");
+			device_printf(dev, "attaching PHYs failed\n");
 			goto fail;
 		}
 	}
@@ -895,7 +899,7 @@ fxp_attach(device_t dev)
 		FXP_LOCK(sc);
 		/* Clear wakeup events. */
 		CSR_WRITE_1(sc, FXP_CSR_PMDR, CSR_READ_1(sc, FXP_CSR_PMDR));
-		fxp_init_body(sc);
+		fxp_init_body(sc, 1);
 		fxp_stop(sc);
 		FXP_UNLOCK(sc);
 	}
@@ -1057,7 +1061,7 @@ fxp_suspend(device_t dev)
 			pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
 			sc->flags |= FXP_FLAG_WOL;
 			/* Reconfigure hardware to accept magic frames. */
-			fxp_init_body(sc);
+			fxp_init_body(sc, 1);
 		}
 		pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2);
 	}
@@ -1099,7 +1103,7 @@ fxp_resume(device_t dev)
 
 	/* reinitialize interface if necessary */
 	if (ifp->if_flags & IFF_UP)
-		fxp_init_body(sc);
+		fxp_init_body(sc, 1);
 
 	sc->suspended = 0;
 
@@ -2100,7 +2104,7 @@ fxp_tick(void *xsc)
 	if (sc->rx_idle_secs > FXP_MAX_RX_IDLE) {
 		sc->rx_idle_secs = 0;
 		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
-			fxp_init_body(sc);
+			fxp_init_body(sc, 1);
 		return;
 	}
 	/*
@@ -2198,7 +2202,7 @@ fxp_watchdog(struct fxp_softc *sc)
 	device_printf(sc->dev, "device timeout\n");
 	sc->ifp->if_oerrors++;
 
-	fxp_init_body(sc);
+	fxp_init_body(sc, 1);
 }
 
 /*
@@ -2212,7 +2216,7 @@ fxp_init(void *xsc)
 	struct fxp_softc *sc = xsc;
 
 	FXP_LOCK(sc);
-	fxp_init_body(sc);
+	fxp_init_body(sc, 1);
 	FXP_UNLOCK(sc);
 }
 
@@ -2221,9 +2225,10 @@ fxp_init(void *xsc)
  * softc lock held.
  */
 static void
-fxp_init_body(struct fxp_softc *sc)
+fxp_init_body(struct fxp_softc *sc, int setmedia)
 {
 	struct ifnet *ifp = sc->ifp;
+	struct mii_data *mii;
 	struct fxp_cb_config *cbp;
 	struct fxp_cb_ias *cb_ias;
 	struct fxp_cb_tx *tcbp;
@@ -2358,7 +2363,7 @@ fxp_init_body(struct fxp_softc *sc)
 	cbp->vlan_strip_en =	((sc->flags & FXP_FLAG_EXT_RFA) != 0 &&
 	    (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) ? 1 : 0;
 
-	if (sc->tunable_noflow || sc->revision == FXP_REV_82557) {
+	if (sc->revision == FXP_REV_82557) {
 		/*
 		 * The 82557 has no hardware flow control, the values
 		 * below are the defaults for the chip.
@@ -2372,12 +2377,30 @@ fxp_init_body(struct fxp_softc *sc)
 		cbp->fc_filter =	0;
 		cbp->pri_fc_loc =	1;
 	} else {
-		cbp->fc_delay_lsb =	0x1f;
-		cbp->fc_delay_msb =	0x01;
+		/* Set pause RX FIFO threshold to 1KB. */
+		CSR_WRITE_1(sc, FXP_CSR_FC_THRESH, 1);
+		/* Set pause time. */
+		cbp->fc_delay_lsb =	0xff;
+		cbp->fc_delay_msb =	0xff;
 		cbp->pri_fc_thresh =	3;
-		cbp->tx_fc_dis =	0;	/* enable transmit FC */
-		cbp->rx_fc_restop =	1;	/* enable FC restop frames */
-		cbp->rx_fc_restart =	1;	/* enable FC restart frames */
+		mii = device_get_softc(sc->miibus);
+		if ((IFM_OPTIONS(mii->mii_media_active) &
+		    IFM_ETH_TXPAUSE) != 0)
+			/* enable transmit FC */
+			cbp->tx_fc_dis = 0;
+		else
+			/* disable transmit FC */
+			cbp->tx_fc_dis = 1;
+		if ((IFM_OPTIONS(mii->mii_media_active) &
+		    IFM_ETH_RXPAUSE) != 0) {
+			/* enable FC restart/restop frames */
+			cbp->rx_fc_restart = 1;
+			cbp->rx_fc_restop = 1;
+		} else {
+			/* disable FC restart/restop frames */
+			cbp->rx_fc_restart = 0;
+			cbp->rx_fc_restop = 0;
+		}
 		cbp->fc_filter =	!prm;	/* drop FC frames to host */
 		cbp->pri_fc_loc =	1;	/* FC pri location (byte31) */
 	}
@@ -2476,10 +2499,7 @@ fxp_init_body(struct fxp_softc *sc)
 	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->fxp_desc.rx_head->rx_addr);
 	fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START);
 
-	/*
-	 * Set current media.
-	 */
-	if (sc->miibus != NULL)
+	if (sc->miibus != NULL && setmedia != 0)
 		mii_mediachg(device_get_softc(sc->miibus));
 
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -2735,6 +2755,31 @@ fxp_miibus_writereg(device_t dev, int ph
 		device_printf(dev, "fxp_miibus_writereg: timed out\n");
 }
 
+static void
+fxp_miibus_statchg(device_t dev)
+{
+	struct fxp_softc *sc;
+	struct mii_data *mii;
+	struct ifnet *ifp;
+
+	sc = device_get_softc(dev);
+	mii = device_get_softc(sc->miibus);
+	ifp = sc->ifp;
+	if (mii == NULL || ifp == NULL ||
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+	    (mii->mii_media_status & (IFM_AVALID | IFM_ACTIVE)) !=
+	    (IFM_AVALID | IFM_ACTIVE))
+		return;
+
+	/*
+	 * Call fxp_init_body in order to adjust the flow control settings.
+	 * Note that the 82557 doesn't support hardware flow control.
+	 */
+	if (sc->revision == FXP_REV_82557)
+		return;
+	fxp_init_body(sc, 0);
+}
+
 static int
 fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 {
@@ -2756,9 +2801,9 @@ fxp_ioctl(struct ifnet *ifp, u_long comm
 			if (((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) &&
 			    ((ifp->if_flags ^ sc->if_flags) &
 			    (IFF_PROMISC | IFF_ALLMULTI | IFF_LINK0)) != 0)
-				fxp_init_body(sc);
+				fxp_init_body(sc, 1);
 			else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
-				fxp_init_body(sc);
+				fxp_init_body(sc, 1);
 		} else {
 			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
 				fxp_stop(sc);
@@ -2860,7 +2905,7 @@ fxp_ioctl(struct ifnet *ifp, u_long comm
 			reinit++;
 		}
 		if (reinit > 0 && ifp->if_flags & IFF_UP)
-			fxp_init_body(sc);
+			fxp_init_body(sc, 1);
 		FXP_UNLOCK(sc);
 		VLAN_CAPABILITIES(ifp);
 		break;
@@ -3051,22 +3096,16 @@ fxp_sysctl_node(struct fxp_softc *sc)
 	    "FXP driver receive interrupt microcode bundle size limit");
 	SYSCTL_ADD_INT(ctx, child,OID_AUTO, "rnr", CTLFLAG_RD, &sc->rnr, 0,
 	    "FXP RNR events");
-	SYSCTL_ADD_INT(ctx, child,
-	    OID_AUTO, "noflow", CTLFLAG_RW, &sc->tunable_noflow, 0,
-	    "FXP flow control disabled");
 
 	/*
 	 * Pull in device tunables.
 	 */
 	sc->tunable_int_delay = TUNABLE_INT_DELAY;
 	sc->tunable_bundle_max = TUNABLE_BUNDLE_MAX;
-	sc->tunable_noflow = 1;
 	(void) resource_int_value(device_get_name(sc->dev),
 	    device_get_unit(sc->dev), "int_delay", &sc->tunable_int_delay);
 	(void) resource_int_value(device_get_name(sc->dev),
 	    device_get_unit(sc->dev), "bundle_max", &sc->tunable_bundle_max);
-	(void) resource_int_value(device_get_name(sc->dev),
-	    device_get_unit(sc->dev), "noflow", &sc->tunable_noflow);
 	sc->rnr = 0;
 
 	hsp = &sc->fxp_hwstats;

Modified: stable/7/sys/dev/fxp/if_fxpreg.h
==============================================================================
--- stable/7/sys/dev/fxp/if_fxpreg.h	Sun Nov 28 15:59:39 2010	(r216002)
+++ stable/7/sys/dev/fxp/if_fxpreg.h	Sun Nov 28 15:59:45 2010	(r216003)
@@ -45,7 +45,8 @@
 #define	FXP_CSR_FLASHCONTROL	12	/* flash control (2 bytes) */
 #define	FXP_CSR_EEPROMCONTROL	14	/* eeprom control (2 bytes) */
 #define	FXP_CSR_MDICONTROL	16	/* mdi control (4 bytes) */
-#define	FXP_CSR_FLOWCONTROL	0x19	/* flow control (2 bytes) */
+#define	FXP_CSR_FC_THRESH	0x19	/* flow control (1 byte) */
+#define	FXP_CSR_FC_STATUS	0x1A	/* flow control status (1 byte) */
 #define	FXP_CSR_PMDR		0x1B	/* power management driver (1 byte) */
 #define	FXP_CSR_GENCONTROL	0x1C	/* general control (1 byte) */
 

Modified: stable/7/sys/dev/fxp/if_fxpvar.h
==============================================================================
--- stable/7/sys/dev/fxp/if_fxpvar.h	Sun Nov 28 15:59:39 2010	(r216002)
+++ stable/7/sys/dev/fxp/if_fxpvar.h	Sun Nov 28 15:59:45 2010	(r216003)
@@ -210,7 +210,6 @@ struct fxp_softc {
 	device_t dev;
 	int tunable_int_delay;		/* interrupt delay value for ucode */
 	int tunable_bundle_max;		/* max # frames per interrupt (ucode) */
-	int tunable_noflow;		/* flow control disabled */
 	int rnr;			/* RNR events */
 	int eeprom_size;		/* size of serial EEPROM */
 	int suspended;			/* 0 = normal  1 = suspended or dead */


More information about the svn-src-all mailing list