em/emx: Integrate ifmedia flow control support.
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 25 Nov 2015 03:30:35 +0000 (11:30 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 25 Nov 2015 05:58:39 +0000 (13:58 +0800)
Other minor bits:
- Set media to IFM_NONE, if there is no link yet.
- Remove no longer used dev.em.Y.flow_ctrl sysctl node.
  ifconfig emY [mediaopt|-mediaopt] [rxpause|txpause|forcepause]
  should be used instead.

share/man/man4/em.4
sys/dev/netif/em/if_em.c
sys/dev/netif/em/if_em.h
sys/dev/netif/emx/if_emx.c
sys/dev/netif/emx/if_emx.h
sys/dev/netif/ig_hal/e1000_dragonfly.h
sys/dev/netif/ig_hal/e1000_osdep.c

index c303574..a91c4ac 100644 (file)
@@ -160,6 +160,26 @@ drivers support the following media options:
 Forces full-duplex operation
 .It Cm half-duplex
 Forces half-duplex operation.
+.It Cm rxpause
+Enable flow control PAUSE reception.
+This is only supported by
+.Cm autoselect
+and
+.Cm full-duplex
+mode.
+.It Cm txpause
+Enable flow control PAUSE transmission.
+This is only supported by
+.Cm autoselect
+and
+.Cm full-duplex
+mode.
+.It Cm forcepause
+Force flow control PAUSE operation as configured by
+.Cm rxpause
+and
+.Cm txpause
+media options.
 .El
 .Pp
 Only use
@@ -335,6 +355,20 @@ perform certain optimization based on the knowledge
 that the interrupt is not shared.
 These tunables also applies to
 .Nm emx .
+.It Va hw.em.flow_ctrl Va hw.emY.flow_ctrl
+The default flow control settings.
+Supported values are:
+rxpause (only enable PAUSE reception),
+txpause (only enable PAUSE transmission),
+full (enable PAUSE reception and transmission),
+none (disable flow control PAUSE operation),
+force-rxpause (force PAUSE reception),
+force-txpause (force PAUSE transmission),
+force-full (forcefully enable PAUSE reception and transmission),
+force-none (forcefully disable flow control PAUSE operation).
+Default is rxpause.
+These tunables also applies to
+.Nm emx .
 .It Va hw.emx.rxr Va hw.emxY.rxr
 This tunable specifies the number of reception queues could be enabled.
 Maximum allowed value for these tunables is 2.
index ca73ca4..77ecca9 100644 (file)
@@ -329,7 +329,6 @@ static int  em_sysctl_stats(SYSCTL_HANDLER_ARGS);
 static int     em_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
 static int     em_sysctl_int_throttle(SYSCTL_HANDLER_ARGS);
 static int     em_sysctl_int_tx_nsegs(SYSCTL_HANDLER_ARGS);
-static int     em_sysctl_flowctrl(SYSCTL_HANDLER_ARGS);
 static void    em_add_sysctl(struct adapter *adapter);
 
 /* Management and WOL Support */
@@ -376,7 +375,7 @@ static int  em_debug_sbp = FALSE;
 static int     em_82573_workaround = 1;
 static int     em_msi_enable = 1;
 
-static char    em_flowctrl[E1000_FC_STRLEN] = E1000_FC_STR_RX_PAUSE;
+static char    em_flowctrl[IFM_ETH_FC_STRLEN] = IFM_ETH_FC_RXPAUSE;
 
 TUNABLE_INT("hw.em.int_throttle_ceil", &em_int_throttle_ceil);
 TUNABLE_INT("hw.em.rxd", &em_rxd);
@@ -432,14 +431,14 @@ em_attach(device_t dev)
        int error = 0;
        uint16_t eeprom_data, device_id, apme_mask;
        driver_intr_t *intr_func;
-       char flowctrl[E1000_FC_STRLEN];
+       char flowctrl[IFM_ETH_FC_STRLEN];
 
        adapter->dev = adapter->osdep.dev = dev;
 
        callout_init_mp(&adapter->timer);
        callout_init_mp(&adapter->tx_fifo_timer);
 
-       ifmedia_init(&adapter->media, IFM_IMASK,
+       ifmedia_init(&adapter->media, IFM_IMASK | IFM_ETH_FCMASK,
            em_media_change, em_media_status);
 
        /* Determine hardware and mac info */
@@ -794,10 +793,10 @@ em_attach(device_t dev)
        /* Setup flow control. */
        device_getenv_string(dev, "flow_ctrl", flowctrl, sizeof(flowctrl),
            em_flowctrl);
-       adapter->flow_ctrl = e1000_str2fc(flowctrl);
+       adapter->ifm_flowctrl = ifmedia_str2ethfc(flowctrl);
        if (adapter->hw.mac.type == e1000_pchlan) {
-               /* Only pause reception is supported */
-               adapter->flow_ctrl = e1000_fc_rx_pause;
+               /* Only PAUSE reception is supported on PCH */
+               adapter->ifm_flowctrl &= ~IFM_ETH_TXPAUSE;
        }
 
        /* Setup OS specific network interface */
@@ -1540,10 +1539,14 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
        ifmr->ifm_status = IFM_AVALID;
        ifmr->ifm_active = IFM_ETHER;
 
-       if (!adapter->link_active)
+       if (!adapter->link_active) {
+               ifmr->ifm_active |= IFM_NONE;
                return;
+       }
 
        ifmr->ifm_status |= IFM_ACTIVE;
+       if (adapter->ifm_flowctrl & IFM_ETH_FORCEPAUSE)
+               ifmr->ifm_active |= IFM_ETH_FORCEPAUSE;
 
        if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
            adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
@@ -1568,6 +1571,10 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
                else
                        ifmr->ifm_active |= IFM_HDX;
        }
+       if (ifmr->ifm_active & IFM_FDX) {
+               ifmr->ifm_active |=
+                   e1000_fc2ifmedia(adapter->hw.fc.current_mode);
+       }
 }
 
 static int
@@ -1581,6 +1588,13 @@ em_media_change(struct ifnet *ifp)
        if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
                return (EINVAL);
 
+       if (adapter->hw.mac.type == e1000_pchlan &&
+           (IFM_OPTIONS(ifm->ifm_media) & IFM_ETH_TXPAUSE)) {
+               if (bootverbose)
+                       if_printf(ifp, "TX PAUSE is not supported on PCH\n");
+               return EINVAL;
+       }
+
        switch (IFM_SUBTYPE(ifm->ifm_media)) {
        case IFM_AUTO:
                adapter->hw.mac.autoneg = DO_AUTO_NEG;
@@ -1595,29 +1609,52 @@ em_media_change(struct ifnet *ifp)
                break;
 
        case IFM_100_TX:
-               adapter->hw.mac.autoneg = FALSE;
-               adapter->hw.phy.autoneg_advertised = 0;
-               if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
+               if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
                        adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_FULL;
-               else
+               } else {
+                       if (IFM_OPTIONS(ifm->ifm_media) &
+                           (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE)) {
+                               if (bootverbose) {
+                                       if_printf(ifp, "Flow control is not "
+                                           "allowed for half-duplex\n");
+                               }
+                               return EINVAL;
+                       }
                        adapter->hw.mac.forced_speed_duplex = ADVERTISE_100_HALF;
+               }
+               adapter->hw.mac.autoneg = FALSE;
+               adapter->hw.phy.autoneg_advertised = 0;
                break;
 
        case IFM_10_T:
-               adapter->hw.mac.autoneg = FALSE;
-               adapter->hw.phy.autoneg_advertised = 0;
-               if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
+               if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
                        adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_FULL;
-               else
+               } else {
+                       if (IFM_OPTIONS(ifm->ifm_media) &
+                           (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE)) {
+                               if (bootverbose) {
+                                       if_printf(ifp, "Flow control is not "
+                                           "allowed for half-duplex\n");
+                               }
+                               return EINVAL;
+                       }
                        adapter->hw.mac.forced_speed_duplex = ADVERTISE_10_HALF;
+               }
+               adapter->hw.mac.autoneg = FALSE;
+               adapter->hw.phy.autoneg_advertised = 0;
                break;
 
        default:
-               if_printf(ifp, "Unsupported media type\n");
-               break;
+               if (bootverbose) {
+                       if_printf(ifp, "Unsupported media type %d\n",
+                           IFM_SUBTYPE(ifm->ifm_media));
+               }
+               return EINVAL;
        }
+       adapter->ifm_flowctrl = ifm->ifm_media & IFM_ETH_FCMASK;
 
-       em_init(adapter);
+       if (ifp->if_flags & IFF_RUNNING)
+               em_init(adapter);
 
        return (0);
 }
@@ -2101,10 +2138,26 @@ em_update_link_status(struct adapter *adapter)
                        E1000_WRITE_REG(hw, E1000_TARC(0), tarc0);
                }
                if (bootverbose) {
-                       device_printf(dev, "Link is up %d Mbps %s\n",
+                       char flowctrl[IFM_ETH_FC_STRLEN];
+
+                       e1000_fc2str(hw->fc.current_mode, flowctrl,
+                           sizeof(flowctrl));
+                       device_printf(dev, "Link is up %d Mbps %s, "
+                           "Flow control: %s\n",
                            adapter->link_speed,
-                           ((adapter->link_duplex == FULL_DUPLEX) ?
-                           "Full Duplex" : "Half Duplex"));
+                           (adapter->link_duplex == FULL_DUPLEX) ?
+                           "Full Duplex" : "Half Duplex",
+                           flowctrl);
+               }
+               if (adapter->ifm_flowctrl & IFM_ETH_FORCEPAUSE) {
+                       enum e1000_fc_mode fc;
+
+                       fc = e1000_ifmedia2fc(adapter->ifm_flowctrl);
+                       if (hw->fc.current_mode != fc) {
+                               hw->fc.requested_mode = fc;
+                               hw->fc.current_mode = fc;
+                               e1000_force_mac_fc(hw);
+                       }
                }
                adapter->link_active = 1;
                adapter->smartspeed = 0;
@@ -2455,15 +2508,17 @@ em_reset(struct adapter *adapter)
 
        adapter->hw.fc.send_xon = TRUE;
 
-       adapter->hw.fc.requested_mode = adapter->flow_ctrl;
+       adapter->hw.fc.requested_mode = e1000_ifmedia2fc(adapter->ifm_flowctrl);
 
        /*
         * Device specific overrides/settings
         */
        switch (adapter->hw.mac.type) {
        case e1000_pchlan:
-               /* Workaround: no TX flow ctrl for PCH */
-               adapter->hw.fc.requested_mode = e1000_fc_rx_pause;
+               KASSERT(adapter->hw.fc.requested_mode == e1000_fc_rx_pause ||
+                   adapter->hw.fc.requested_mode == e1000_fc_none,
+                   ("unsupported flow control on PCH %d",
+                    adapter->hw.fc.requested_mode));
                adapter->hw.fc.pause_time = 0xFFFF; /* override */
                if (adapter->arpcom.ac_if.if_mtu > ETHERMTU) {
                        adapter->hw.fc.high_water = 0x3500;
@@ -2572,7 +2627,6 @@ em_setup_ifp(struct adapter *adapter)
                        fiber_type = IFM_1000_LX;
                ifmedia_add(&adapter->media, IFM_ETHER | fiber_type | IFM_FDX, 
                            0, NULL);
-               ifmedia_add(&adapter->media, IFM_ETHER | fiber_type, 0, NULL);
        } else {
                ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL);
                ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T | IFM_FDX,
@@ -2584,12 +2638,11 @@ em_setup_ifp(struct adapter *adapter)
                if (adapter->hw.phy.type != e1000_phy_ife) {
                        ifmedia_add(&adapter->media,
                                IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
-                       ifmedia_add(&adapter->media,
-                               IFM_ETHER | IFM_1000_T, 0, NULL);
                }
        }
        ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
-       ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
+       ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO |
+           adapter->ifm_flowctrl);
 }
 
 
@@ -4089,7 +4142,6 @@ em_add_sysctl(struct adapter *adapter)
 {
        struct sysctl_ctx_list *ctx;
        struct sysctl_oid *tree;
-       int access;
 
        ctx = device_get_sysctl_ctx(adapter->dev);
        tree = device_get_sysctl_tree(adapter->dev);
@@ -4124,23 +4176,6 @@ em_add_sysctl(struct adapter *adapter)
            OID_AUTO, "wreg_tx_nsegs", CTLFLAG_RW,
            &adapter->tx_wreg_nsegs, 0,
            "# segments before write to hardware register");
-
-       access = CTLFLAG_RW;
-       if (adapter->hw.mac.type == e1000_pchlan) {
-               /*
-                * Only pause reception is supported, so make this
-                * sysctl read-only for PCH.
-                */
-               access = CTLFLAG_RD;
-       }
-       SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
-           OID_AUTO, "flow_ctrl", CTLTYPE_STRING|access, adapter, 0,
-           em_sysctl_flowctrl, "A",
-           "flow control: "
-           E1000_FC_STR_FULL ", "
-           E1000_FC_STR_RX_PAUSE ", "
-           E1000_FC_STR_TX_PAUSE ", "
-           E1000_FC_STR_NONE);
 }
 
 static int
@@ -4426,12 +4461,3 @@ em_tso_setup(struct adapter *adapter, struct mbuf *mp,
        adapter->next_avail_tx_desc = curr_txd;
        return 1;
 }
-
-static int
-em_sysctl_flowctrl(SYSCTL_HANDLER_ARGS)
-{
-       struct adapter *adapter = arg1;
-
-       return e1000_sysctl_flowctrl(&adapter->arpcom.ac_if,
-           &adapter->flow_ctrl, &adapter->hw, oidp, req);
-}
index ff53ab1..d20652d 100644 (file)
@@ -393,7 +393,7 @@ struct adapter {
        struct mbuf             *fmp;
        struct mbuf             *lmp;
 
-       enum e1000_fc_mode      flow_ctrl;
+       int                     ifm_flowctrl;
 
        /* Misc stats maintained by the driver */
        unsigned long           dropped_pkts;
index 250ec0d..e912615 100644 (file)
@@ -260,7 +260,6 @@ static int  emx_sysctl_tx_wreg_nsegs(SYSCTL_HANDLER_ARGS);
 static int     emx_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS);
 static int     emx_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS);
 #endif
-static int     emx_sysctl_flowctrl(SYSCTL_HANDLER_ARGS);
 static void    emx_add_sysctl(struct emx_softc *);
 
 static void    emx_serialize_skipmain(struct emx_softc *);
@@ -312,7 +311,7 @@ static int  emx_debug_sbp = 0;
 static int     emx_82573_workaround = 1;
 static int     emx_msi_enable = 1;
 
-static char    emx_flowctrl[E1000_FC_STRLEN] = E1000_FC_STR_RX_PAUSE;
+static char    emx_flowctrl[IFM_ETH_FC_STRLEN] = IFM_ETH_FC_RXPAUSE;
 
 TUNABLE_INT("hw.emx.int_throttle_ceil", &emx_int_throttle_ceil);
 TUNABLE_INT("hw.emx.rxd", &emx_rxd);
@@ -436,7 +435,7 @@ emx_attach(device_t dev)
        u_int intr_flags;
        uint16_t eeprom_data, device_id, apme_mask;
        driver_intr_t *intr_func;
-       char flowctrl[E1000_FC_STRLEN];
+       char flowctrl[IFM_ETH_FC_STRLEN];
 #ifdef IFPOLL_ENABLE
        int offset, offset_def;
 #endif
@@ -486,7 +485,8 @@ emx_attach(device_t dev)
 
        KKASSERT(i == EMX_NSERIALIZE);
 
-       ifmedia_init(&sc->media, IFM_IMASK, emx_media_change, emx_media_status);
+       ifmedia_init(&sc->media, IFM_IMASK | IFM_ETH_FCMASK,
+           emx_media_change, emx_media_status);
        callout_init_mp(&sc->timer);
 
        sc->dev = sc->osdep.dev = dev;
@@ -834,7 +834,7 @@ emx_attach(device_t dev)
        /* Setup flow control. */
        device_getenv_string(dev, "flow_ctrl", flowctrl, sizeof(flowctrl),
            emx_flowctrl);
-       sc->flow_ctrl = e1000_str2fc(flowctrl);
+       sc->ifm_flowctrl = ifmedia_str2ethfc(flowctrl);
 
        /* Setup OS specific network interface */
        emx_setup_ifp(sc);
@@ -1483,10 +1483,14 @@ emx_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
        ifmr->ifm_status = IFM_AVALID;
        ifmr->ifm_active = IFM_ETHER;
 
-       if (!sc->link_active)
+       if (!sc->link_active) {
+               ifmr->ifm_active |= IFM_NONE;
                return;
+       }
 
        ifmr->ifm_status |= IFM_ACTIVE;
+       if (sc->ifm_flowctrl & IFM_ETH_FORCEPAUSE)
+               ifmr->ifm_active |= IFM_ETH_FORCEPAUSE;
 
        if (sc->hw.phy.media_type == e1000_media_type_fiber ||
            sc->hw.phy.media_type == e1000_media_type_internal_serdes) {
@@ -1509,6 +1513,8 @@ emx_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
                else
                        ifmr->ifm_active |= IFM_HDX;
        }
+       if (ifmr->ifm_active & IFM_FDX)
+               ifmr->ifm_active |= e1000_fc2ifmedia(sc->hw.fc.current_mode);
 }
 
 static int
@@ -1528,7 +1534,6 @@ emx_media_change(struct ifnet *ifp)
                sc->hw.phy.autoneg_advertised = EMX_AUTONEG_ADV_DEFAULT;
                break;
 
-       case IFM_1000_LX:
        case IFM_1000_SX:
        case IFM_1000_T:
                sc->hw.mac.autoneg = EMX_DO_AUTO_NEG;
@@ -1536,29 +1541,52 @@ emx_media_change(struct ifnet *ifp)
                break;
 
        case IFM_100_TX:
-               sc->hw.mac.autoneg = FALSE;
-               sc->hw.phy.autoneg_advertised = 0;
-               if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
+               if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
                        sc->hw.mac.forced_speed_duplex = ADVERTISE_100_FULL;
-               else
+               } else {
+                       if (IFM_OPTIONS(ifm->ifm_media) &
+                           (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE)) {
+                               if (bootverbose) {
+                                       if_printf(ifp, "Flow control is not "
+                                           "allowed for half-duplex\n");
+                               }
+                               return EINVAL;
+                       }
                        sc->hw.mac.forced_speed_duplex = ADVERTISE_100_HALF;
+               }
+               sc->hw.mac.autoneg = FALSE;
+               sc->hw.phy.autoneg_advertised = 0;
                break;
 
        case IFM_10_T:
-               sc->hw.mac.autoneg = FALSE;
-               sc->hw.phy.autoneg_advertised = 0;
-               if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
+               if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
                        sc->hw.mac.forced_speed_duplex = ADVERTISE_10_FULL;
-               else
+               } else {
+                       if (IFM_OPTIONS(ifm->ifm_media) &
+                           (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE)) {
+                               if (bootverbose) {
+                                       if_printf(ifp, "Flow control is not "
+                                           "allowed for half-duplex\n");
+                               }
+                               return EINVAL;
+                       }
                        sc->hw.mac.forced_speed_duplex = ADVERTISE_10_HALF;
+               }
+               sc->hw.mac.autoneg = FALSE;
+               sc->hw.phy.autoneg_advertised = 0;
                break;
 
        default:
-               if_printf(ifp, "Unsupported media type\n");
-               break;
+               if (bootverbose) {
+                       if_printf(ifp, "Unsupported media type %d\n",
+                           IFM_SUBTYPE(ifm->ifm_media));
+               }
+               return EINVAL;
        }
+       sc->ifm_flowctrl = ifm->ifm_media & IFM_ETH_FCMASK;
 
-       emx_init(sc);
+       if (ifp->if_flags & IFF_RUNNING)
+               emx_init(sc);
 
        return (0);
 }
@@ -1844,10 +1872,26 @@ emx_update_link_status(struct emx_softc *sc)
                        E1000_WRITE_REG(hw, E1000_TARC(0), tarc0);
                }
                if (bootverbose) {
-                       device_printf(dev, "Link is up %d Mbps %s\n",
+                       char flowctrl[IFM_ETH_FC_STRLEN];
+
+                       e1000_fc2str(hw->fc.current_mode, flowctrl,
+                           sizeof(flowctrl));
+                       device_printf(dev, "Link is up %d Mbps %s, "
+                           "Flow control: %s\n",
                            sc->link_speed,
-                           ((sc->link_duplex == FULL_DUPLEX) ?
-                           "Full Duplex" : "Half Duplex"));
+                           (sc->link_duplex == FULL_DUPLEX) ?
+                           "Full Duplex" : "Half Duplex",
+                           flowctrl);
+               }
+               if (sc->ifm_flowctrl & IFM_ETH_FORCEPAUSE) {
+                       enum e1000_fc_mode fc;
+
+                       fc = e1000_ifmedia2fc(sc->ifm_flowctrl);
+                       if (hw->fc.current_mode != fc) {
+                               hw->fc.requested_mode = fc;
+                               hw->fc.current_mode = fc;
+                               e1000_force_mac_fc(hw);
+                       }
                }
                sc->link_active = 1;
                sc->smartspeed = 0;
@@ -1981,7 +2025,7 @@ emx_reset(struct emx_softc *sc)
 
        sc->hw.fc.pause_time = EMX_FC_PAUSE_TIME;
        sc->hw.fc.send_xon = TRUE;
-       sc->hw.fc.requested_mode = sc->flow_ctrl;
+       sc->hw.fc.requested_mode = e1000_ifmedia2fc(sc->ifm_flowctrl);
 
        /*
         * Device specific overrides/settings
@@ -2085,7 +2129,6 @@ emx_setup_ifp(struct emx_softc *sc)
            sc->hw.phy.media_type == e1000_media_type_internal_serdes) {
                ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,
                            0, NULL);
-               ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
        } else {
                ifmedia_add(&sc->media, IFM_ETHER | IFM_10_T, 0, NULL);
                ifmedia_add(&sc->media, IFM_ETHER | IFM_10_T | IFM_FDX,
@@ -2096,12 +2139,10 @@ emx_setup_ifp(struct emx_softc *sc)
                if (sc->hw.phy.type != e1000_phy_ife) {
                        ifmedia_add(&sc->media,
                                IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
-                       ifmedia_add(&sc->media,
-                               IFM_ETHER | IFM_1000_T, 0, NULL);
                }
        }
        ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
-       ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
+       ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO | sc->ifm_flowctrl);
 }
 
 /*
@@ -3707,15 +3748,6 @@ emx_add_sysctl(struct emx_softc *sc)
            OID_AUTO, "tx_ring_inuse", CTLFLAG_RD, &sc->tx_ring_inuse, 0,
            "# of TX rings used");
 
-       SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
-           OID_AUTO, "flow_ctrl", CTLTYPE_STRING|CTLFLAG_RW, sc, 0,
-           emx_sysctl_flowctrl, "A",
-           "flow control: "
-           E1000_FC_STR_FULL ", "
-           E1000_FC_STR_RX_PAUSE ", "
-           E1000_FC_STR_TX_PAUSE ", "
-           E1000_FC_STR_NONE);
-
 #ifdef IFPOLL_ENABLE
        SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
                        OID_AUTO, "npoll_rxoff", CTLTYPE_INT|CTLFLAG_RW,
@@ -4344,12 +4376,3 @@ emx_get_txring_inuse(const struct emx_softc *sc, boolean_t polling)
        else
                return 1;
 }
-
-static int
-emx_sysctl_flowctrl(SYSCTL_HANDLER_ARGS)
-{
-       struct emx_softc *sc = arg1;
-
-       return e1000_sysctl_flowctrl(&sc->arpcom.ac_if, &sc->flow_ctrl, &sc->hw,
-           oidp, req);
-}
index da8c11a..12b61c2 100644 (file)
@@ -392,7 +392,7 @@ struct emx_softc {
        int                     rx_ring_cnt;
        struct emx_rxdata       rx_data[EMX_NRX_RING];
 
-       enum e1000_fc_mode      flow_ctrl;
+       int                     ifm_flowctrl;
 
        /* Misc stats maintained by the driver */
        unsigned long           rx_overruns;
index d5718b5..5454b31 100644 (file)
 #ifndef _E1000_DRAGONFLY_H_
 #define _E1000_DRAGONFLY_H_
 
-#define E1000_FC_STRLEN                16
-#define E1000_FC_STR_RX_PAUSE  "rx_pause"
-#define E1000_FC_STR_TX_PAUSE  "tx_pause"
-#define E1000_FC_STR_FULL      "full"
-#define E1000_FC_STR_NONE      "none"
-
 struct ifnet;
 struct sysctl_oid;
 struct sysctl_req;
 
 void   e1000_fc2str(enum e1000_fc_mode fc, char *str, int len);
-enum e1000_fc_mode e1000_str2fc(const char *str);
-int    e1000_sysctl_flowctrl(struct ifnet *ifp, enum e1000_fc_mode *fc0,
-           struct e1000_hw *hw, struct sysctl_oid *oidp,
-           struct sysctl_req *req);
-
 enum e1000_fc_mode e1000_ifmedia2fc(int ifm);
 int    e1000_fc2ifmedia(enum e1000_fc_mode fc);
 
index 23cffaa..a7a54aa 100644 (file)
@@ -102,35 +102,22 @@ e1000_write_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
        return E1000_SUCCESS;
 }
 
-enum e1000_fc_mode
-e1000_str2fc(const char *str)
-{
-       if (strcmp(str, E1000_FC_STR_NONE) == 0)
-               return e1000_fc_none;
-       else if (strcmp(str, E1000_FC_STR_RX_PAUSE) == 0)
-               return e1000_fc_rx_pause;
-       else if (strcmp(str, E1000_FC_STR_TX_PAUSE) == 0)
-               return e1000_fc_tx_pause;
-       else
-               return e1000_fc_full;
-}
-
 void
 e1000_fc2str(enum e1000_fc_mode fc, char *str, int len)
 {
-       const char *fc_str = E1000_FC_STR_FULL;
+       const char *fc_str = IFM_ETH_FC_NONE;
 
        switch (fc) {
-       case e1000_fc_none:
-               fc_str = E1000_FC_STR_NONE;
+       case e1000_fc_full:
+               fc_str = IFM_ETH_FC_FULL;
                break;
 
        case e1000_fc_rx_pause:
-               fc_str = E1000_FC_STR_RX_PAUSE;
+               fc_str = IFM_ETH_FC_RXPAUSE;
                break;
 
        case e1000_fc_tx_pause:
-               fc_str = E1000_FC_STR_TX_PAUSE;
+               fc_str = IFM_ETH_FC_TXPAUSE;
                break;
 
        default:
@@ -139,35 +126,6 @@ e1000_fc2str(enum e1000_fc_mode fc, char *str, int len)
        strlcpy(str, fc_str, len);
 }
 
-int
-e1000_sysctl_flowctrl(struct ifnet *ifp, enum e1000_fc_mode *fc0,
-    struct e1000_hw *hw, struct sysctl_oid *oidp, struct sysctl_req *req)
-{
-       char flowctrl[E1000_FC_STRLEN];
-       enum e1000_fc_mode fc;
-       int error;
-
-       e1000_fc2str(*fc0, flowctrl, sizeof(flowctrl));
-       error = sysctl_handle_string(oidp, flowctrl, sizeof(flowctrl), req);
-       if (error != 0 || req->newptr == NULL)
-               return error;
-
-       fc = e1000_str2fc(flowctrl);
-
-       ifnet_serialize_all(ifp);
-       if (fc == *fc0)
-               goto done;
-
-       *fc0 = fc;
-       hw->fc.requested_mode = fc;
-       hw->fc.current_mode = fc;
-       e1000_force_mac_fc(hw);
-done:
-       ifnet_deserialize_all(ifp);
-
-       return 0;
-}
-
 enum e1000_fc_mode
 e1000_ifmedia2fc(int ifm)
 {