[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    bnx(4) flow control support.
From:       Brad <brad () comstyle ! com>
Date:       2010-06-28 19:34:23
Message-ID: 20100628193419.GA22771 () rox ! home ! comstyle ! com
[Download RAW message or body]

Here is an older diff I had to add flow control support to bnx(4)
which I have dug out and updated to -current src. I have tested
it with the following adapters and could use some testing with a
BCM5709 chipset. This supports flow control on all copper adapters
and BCM5706 with fiber, but not BCM5708/BCM5709 with fiber yet.

bnx0 at pci1 dev 7 function 0 "Broadcom BCM5706" rev 0x02: apic 2 int 16 (irq 12)
bnx0: address 00:10:18:15:f8:8a
brgphy1 at bnx0 phy 1: BCM5706 10/100/1000baseT/SX PHY, rev. 2

bnx1 at pci5 dev 0 function 0 "Broadcom BCM5708" rev 0x11: apic 2 int 16 (irq 12)
bnx1: address 00:10:18:15:fa:3e
brgphy2 at bnx1 phy 1: BCM5708C 10/100/1000baseT PHY, rev. 5

Please test with any bnx(4) chipsets and provide a dmesg.


Index: if_bnx.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bnx.c,v
retrieving revision 1.88
diff -u -p -r1.88 if_bnx.c
--- if_bnx.c	24 May 2010 21:23:23 -0000	1.88
+++ if_bnx.c	28 Jun 2010 19:15:52 -0000
@@ -913,6 +913,9 @@ bnx_attachhook(void *xsc)
 	/* Look for our PHY. */
 	ifmedia_init(&sc->bnx_mii.mii_media, 0, bnx_ifmedia_upd,
 	    bnx_ifmedia_sts);
+	if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5706 ||
+	    (!(sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG)))
+		mii_flags |= MIIF_DOPAUSE;
 	if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG)
 		mii_flags |= MIIF_HAVEFIBER;
 	mii_attach(&sc->bnx_dev, &sc->bnx_mii, 0xffffffff,
@@ -1279,6 +1282,7 @@ bnx_miibus_statchg(struct device *dev)
 {
 	struct bnx_softc	*sc = (struct bnx_softc *)dev;
 	struct mii_data		*mii = &sc->bnx_mii;
+	u_int32_t		rx_mode = sc->rx_mode;
 	int			val;
 
 	val = REG_RD(sc, BNX_EMAC_MODE);
@@ -1286,6 +1290,15 @@ bnx_miibus_statchg(struct device *dev)
 		BNX_EMAC_MODE_MAC_LOOP | BNX_EMAC_MODE_FORCE_LINK | 
 		BNX_EMAC_MODE_25G);
 
+	/*
+	 * Get flow control negotiation result.
+	 */
+	if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO &&
+	    (mii->mii_media_active & IFM_ETH_FMASK) != sc->bnx_flowflags) {
+		sc->bnx_flowflags = mii->mii_media_active & IFM_ETH_FMASK;
+		mii->mii_media_active &= ~IFM_ETH_FMASK;
+	}
+
 	/* Set MII or GMII interface based on the speed
 	 * negotiated by the PHY.
 	 */
@@ -1325,6 +1338,34 @@ bnx_miibus_statchg(struct device *dev)
 		DBPRINT(sc, BNX_INFO, "Setting Full-Duplex interface.\n");
 
 	REG_WR(sc, BNX_EMAC_MODE, val);
+
+	/*
+	 * 802.3x flow control
+	 */
+	if (sc->bnx_flowflags & IFM_ETH_RXPAUSE) {
+		DBPRINT(sc, BNX_INFO, "Enabling RX mode flow control.\n");
+		rx_mode |= BNX_EMAC_RX_MODE_FLOW_EN;
+	} else {
+		DBPRINT(sc, BNX_INFO, "Disabling RX mode flow control.\n");
+		rx_mode &= ~BNX_EMAC_RX_MODE_FLOW_EN;
+	}
+
+	if (sc->bnx_flowflags & IFM_ETH_TXPAUSE) {
+		DBPRINT(sc, BNX_INFO, "Enabling TX mode flow control.\n");
+		BNX_SETBIT(sc, BNX_EMAC_TX_MODE, BNX_EMAC_TX_MODE_FLOW_EN);
+	} else {
+		DBPRINT(sc, BNX_INFO, "Disabling TX mode flow control.\n");
+		BNX_CLRBIT(sc, BNX_EMAC_TX_MODE, BNX_EMAC_TX_MODE_FLOW_EN);
+	}
+
+	/* Only make changes if the recive mode has actually changed. */
+	if (rx_mode != sc->rx_mode) {
+		DBPRINT(sc, BNX_VERBOSE, "Enabling new receive mode: 0x%08X\n",
+		    rx_mode);
+
+		sc->rx_mode = rx_mode;
+		REG_WR(sc, BNX_EMAC_RX_MODE, rx_mode);
+	}
 }
 
 /****************************************************************************/
@@ -3954,6 +3995,13 @@ bnx_init_rx_context(struct bnx_softc *sc
 	val = BNX_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE |
 		BNX_L2CTX_CTX_TYPE_SIZE_L2 | (0x02 << 8);
 
+	/*
+	 * Set the level for generating pause frames
+	 * when the number of available rx_bd's gets
+	 * too low (the low watermark) and the level
+	 * when pause frames can be stopped (the high
+	 * watermark).
+	 */
 	if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5709) {
 		u_int32_t lo_water, hi_water;
 
@@ -3967,7 +4015,8 @@ bnx_init_rx_context(struct bnx_softc *sc
 			hi_water = 0xf;
 		else if (hi_water == 0)
 			lo_water = 0;
-		val |= lo_water |
+
+		val |= (lo_water << BNX_L2CTX_RX_LO_WATER_MARK_SHIFT) |
 		    (hi_water << BNX_L2CTX_RX_HI_WATER_MARK_SHIFT);
 	}
 
@@ -4202,8 +4251,9 @@ bnx_ifmedia_sts(struct ifnet *ifp, struc
 	mii = &sc->bnx_mii;
 
 	mii_pollstat(mii);
-	ifmr->ifm_active = mii->mii_media_active;
 	ifmr->ifm_status = mii->mii_media_status;
+	ifmr->ifm_active = (mii->mii_media_active & ~IFM_ETH_FMASK) |
+	    sc->bnx_flowflags;
 
 	splx(s);
 }
@@ -5091,6 +5141,20 @@ bnx_ioctl(struct ifnet *ifp, u_long comm
 		break;
 
 	case SIOCSIFMEDIA:
+		/* Flow control requires full-duplex mode. */
+		if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO ||
+		    (ifr->ifr_media & IFM_FDX) == 0)
+			ifr->ifr_media &= ~IFM_ETH_FMASK;
+
+		if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) {
+			if ((ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) {
+				/* We can do both TXPAUSE and RXPAUSE. */
+				ifr->ifr_media |=
+				    IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;
+			}
+			sc->bnx_flowflags = ifr->ifr_media & IFM_ETH_FMASK;
+		}
+		/* FALLTHROUGH */
 	case SIOCGIFMEDIA:
 		DBPRINT(sc, BNX_VERBOSE, "bnx_phy_flags = 0x%08X\n",
 		    sc->bnx_phy_flags);
Index: if_bnxreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bnxreg.h,v
retrieving revision 1.35
diff -u -p -r1.35 if_bnxreg.h
--- if_bnxreg.h	24 May 2010 21:23:23 -0000	1.35
+++ if_bnxreg.h	28 Jun 2010 19:15:55 -0000
@@ -4809,6 +4809,8 @@ struct bnx_softc {
 	u_int32_t		bnx_shared_hw_cfg;
 	u_int32_t		bnx_port_hw_cfg;
 
+	int			bnx_flowflags;
+
 	u_int16_t		bus_speed_mhz;		/* PCI bus speed */
 	struct flash_spec	*bnx_flash_info;	/* Flash NVRAM settings */
 	u_int32_t		bnx_flash_size;		/* Flash NVRAM size */

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic