The following diff adds flow control support for bnx(4).

Please provide a dmesg and "ifconfig bnxX" output.


Index: if_bnx.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bnx.c,v
retrieving revision 1.81
diff -u -p -r1.81 if_bnx.c
--- if_bnx.c    3 Jul 2009 04:54:05 -0000       1.81
+++ if_bnx.c    25 Jul 2009 13:06:48 -0000
@@ -909,6 +910,7 @@ bnx_attachhook(void *xsc)
        /* Look for our PHY. */
        ifmedia_init(&sc->bnx_mii.mii_media, 0, bnx_ifmedia_upd,
            bnx_ifmedia_sts);
+       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,
@@ -1255,6 +1257,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);
@@ -1262,6 +1265,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.
         */
@@ -1301,6 +1313,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);
+       }
 }
 
 /****************************************************************************/
@@ -4147,8 +4168,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);
 }
@@ -5036,6 +5058,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.32
diff -u -p -r1.32 if_bnxreg.h
--- if_bnxreg.h 3 Jul 2009 06:20:16 -0000       1.32
+++ if_bnxreg.h 25 Jul 2009 13:06:48 -0000
@@ -4803,6 +4803,8 @@ struct bnx_softc {
        /* Values that need to be shared with the PHY driver. */
        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 
*/

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

Reply via email to