mxge: Integrate ifmedia flow control support.
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 26 Nov 2015 06:31:04 +0000 (14:31 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 26 Nov 2015 06:33:47 +0000 (14:33 +0800)
And remove flow control sysctl node.  The following command should
be use to change flow control settings:
ifconfig mxgeX [mediaopt|-mediaopt] flowcontrol

Note, due to hardware limitation, rxpause and txpause could only be
all on or all off.

share/man/man4/mxge.4
sys/dev/netif/mxge/if_mxge.c

index c8c855f..148f2bf 100644 (file)
@@ -31,7 +31,7 @@
 .\"
 .\" $FreeBSD: src/share/man/man4/mxge.4,v 1.7.4.2.4.1 2009/04/15 03:14:26 kensmith Exp $
 .\"
-.Dd November 28, 2014
+.Dd November 26, 2015
 .Dt MXGE 4
 .Os
 .Sh NAME
@@ -77,6 +77,27 @@ All hardware requirements listed apply to use with
 For further hardware information, see
 .Pa http://www.myricom.com .
 .Pp
+The
+.Nm
+driver supports the following media options:
+.Bl -tag -width ".Cm forcepause"
+.It Cm rxpause
+Enable flow control PAUSE reception.
+Due to hardware limitation,
+this will also enable PAUSE transmission.
+.It Cm txpause
+Enable flow control PAUSE transmission.
+Due to hardware limitation,
+this will also enable PAUSE reception.
+.It Cm forcepause
+Force flow control PAUSE operation as configured by
+.Cm rxpause
+and
+.Cm txpause
+media options.
+This media option can't be turned off.
+.El
+.Pp
 For more information on configuring this device, see
 .Xr ifconfig 8 .
 The
@@ -147,9 +168,12 @@ The default value is 0.
 This value delays the generation of all interrupts in units of
 1 microsecond.
 The default value is 150.
-.It Va hw.mxge.flow_control_enabled
-Whether or not hardware flow control is enabled on the adapter.
-The default value is 1.
+.It Va hw.mxge.flow_ctrl
+The default flow control settings.
+Supported values are:
+force-full (forcefully enable PAUSE reception and transmission).
+force-none (forcefully disable flow control PAUSE operation).
+Default is force-full.
 .El
 .Sh MIB Variables
 A number of per-interface variables are implemented in the
@@ -157,7 +181,7 @@ A number of per-interface variables are implemented in the
 branch of the
 .Xr sysctl 3
 MIB.
-.Bl -tag -width "flow_control_enabled"
+.Bl -tag -width "firmware_version"
 .It Va firmware_version
 The version string of firmware that is currently loaded by the driver.
 It is read-only.
@@ -168,9 +192,6 @@ Flipping its value will cause chip reinitialization.
 .It Va intr_coal_delay
 See tunable
 .Va hw.mxge.intr_coal_delay .
-.It Va flow_control_enabled
-See tunable
-.Va hw.mxge.flow_control_enabled .
 .El
 .Sh SUPPORT
 For general information and support,
index cdadbdc..d318bad 100644 (file)
@@ -85,6 +85,8 @@ $FreeBSD: head/sys/dev/mxge/if_mxge.c 254263 2013-08-12 23:30:01Z scottl $
 #include <dev/netif/mxge/mcp_gen_header.h>
 #include <dev/netif/mxge/if_mxge_var.h>
 
+#define MXGE_IFM       (IFM_ETHER | IFM_FDX | IFM_ETH_FORCEPAUSE)
+
 #define MXGE_RX_SMALL_BUFLEN           (MHLEN - MXGEFW_PAD)
 #define MXGE_HWRSS_KEYLEN              16
 
@@ -93,7 +95,6 @@ static int mxge_nvidia_ecrc_enable = 1;
 static int mxge_force_firmware = 0;
 static int mxge_intr_coal_delay = MXGE_INTR_COAL_DELAY;
 static int mxge_deassert_wait = 1;
-static int mxge_flow_control = 1;
 static int mxge_ticks;
 static int mxge_num_slices = 0;
 static int mxge_always_promisc = 0;
@@ -106,13 +107,14 @@ static int mxge_multi_tx = 1;
  */
 static int mxge_use_rss = 0;
 
+static char mxge_flowctrl[IFM_ETH_FC_STRLEN] = IFM_ETH_FC_FORCE_FULL;
+
 static const char *mxge_fw_unaligned = "mxge_ethp_z8e";
 static const char *mxge_fw_aligned = "mxge_eth_z8e";
 static const char *mxge_fw_rss_aligned = "mxge_rss_eth_z8e";
 static const char *mxge_fw_rss_unaligned = "mxge_rss_ethp_z8e";
 
 TUNABLE_INT("hw.mxge.num_slices", &mxge_num_slices);
-TUNABLE_INT("hw.mxge.flow_control_enabled", &mxge_flow_control);
 TUNABLE_INT("hw.mxge.intr_coal_delay", &mxge_intr_coal_delay); 
 TUNABLE_INT("hw.mxge.nvidia_ecrc_enable", &mxge_nvidia_ecrc_enable);   
 TUNABLE_INT("hw.mxge.force_firmware", &mxge_force_firmware);   
@@ -124,6 +126,7 @@ TUNABLE_INT("hw.mxge.multi_tx", &mxge_multi_tx);
 TUNABLE_INT("hw.mxge.use_rss", &mxge_use_rss);
 TUNABLE_INT("hw.mxge.msi.enable", &mxge_msi_enable);
 TUNABLE_INT("hw.mxge.msix.enable", &mxge_msix_enable);
+TUNABLE_STR("hw.mxge.flow_ctrl", mxge_flowctrl, sizeof(mxge_flowctrl));
 
 static int mxge_probe(device_t dev);
 static int mxge_attach(device_t dev);
@@ -1336,29 +1339,6 @@ mxge_change_intr_coal(SYSCTL_HANDLER_ARGS)
        return err;
 }
 
-static int
-mxge_change_flow_control(SYSCTL_HANDLER_ARGS)
-{
-       mxge_softc_t *sc;
-       unsigned int enabled;
-       int err;
-
-       sc = arg1;
-       enabled = sc->pause;
-       err = sysctl_handle_int(oidp, &enabled, arg2, req);
-       if (err != 0)
-               return err;
-
-       if (enabled == sc->pause)
-               return 0;
-
-       ifnet_serialize_all(sc->ifp);
-       err = mxge_change_pause(sc, enabled);
-       ifnet_deserialize_all(sc->ifp);
-
-       return err;
-}
-
 static int
 mxge_handle_be32(SYSCTL_HANDLER_ARGS)
 {
@@ -1455,10 +1435,6 @@ mxge_add_sysctls(mxge_softc_t *sc)
            CTLTYPE_INT|CTLFLAG_RW, sc, 0, mxge_change_throttle, "I",
            "Transmit throttling");
 
-       SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "flow_control_enabled",
-           CTLTYPE_INT|CTLFLAG_RW, sc, 0, mxge_change_flow_control, "I",
-           "Interrupt coalescing delay in usecs");
-
        SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "use_rss",
            CTLTYPE_INT|CTLFLAG_RW, sc, 0, mxge_change_use_rss, "I",
            "Use RSS");
@@ -2452,11 +2428,17 @@ static struct mxge_media_type mxge_sfp_media_types[] = {
 static void
 mxge_media_set(mxge_softc_t *sc, int media_type)
 {
+       int fc_opt = 0;
+
        if (media_type == IFM_NONE)
                return;
 
-       ifmedia_add(&sc->media, IFM_ETHER | IFM_FDX | media_type, 0, NULL);
-       ifmedia_set(&sc->media, IFM_ETHER | IFM_FDX | media_type);
+       if (sc->pause)
+               fc_opt = IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE;
+
+       ifmedia_add(&sc->media, MXGE_IFM | media_type, 0, NULL);
+       ifmedia_set(&sc->media, MXGE_IFM | media_type | fc_opt);
+
        sc->current_media = media_type;
 }
 
@@ -3754,7 +3736,20 @@ mxge_tick(void *arg)
 static int
 mxge_media_change(struct ifnet *ifp)
 {
-       return EINVAL;
+       mxge_softc_t *sc = ifp->if_softc;
+       const struct ifmedia *ifm = &sc->media;
+       int pause;
+
+       if (IFM_OPTIONS(ifm->ifm_media) & (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE)) {
+               if (sc->pause)
+                       return 0;
+               pause = 1;
+       } else {
+               if (!sc->pause)
+                       return 0;
+               pause = 0;
+       }
+       return mxge_change_pause(sc, pause);
 }
 
 static int
@@ -3797,8 +3792,11 @@ mxge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
        ifmr->ifm_status |= IFM_ACTIVE;
 
        ifmr->ifm_active |= sc->current_media;
-       if (sc->current_media != IFM_NONE)
-               ifmr->ifm_active |= IFM_FDX;
+       if (sc->current_media != IFM_NONE) {
+               ifmr->ifm_active |= MXGE_IFM;
+               if (sc->pause)
+                       ifmr->ifm_active |= IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE;
+       }
 }
 
 static int
@@ -3867,6 +3865,7 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data,
                break;
 
        case SIOCGIFMEDIA:
+       case SIOCSIFMEDIA:
                err = ifmedia_ioctl(ifp, (struct ifreq *)data,
                    &sc->media, command);
                break;
@@ -3881,6 +3880,8 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data,
 static void
 mxge_fetch_tunables(mxge_softc_t *sc)
 {
+       int ifm;
+
        sc->intr_coal_delay = mxge_intr_coal_delay;
        if (sc->intr_coal_delay < 0 || sc->intr_coal_delay > (10 * 1000))
                sc->intr_coal_delay = MXGE_INTR_COAL_DELAY;
@@ -3889,7 +3890,10 @@ mxge_fetch_tunables(mxge_softc_t *sc)
        if (mxge_ticks == 0)
                mxge_ticks = hz / 2;
 
-       sc->pause = mxge_flow_control;
+       ifm = ifmedia_str2ethfc(mxge_flowctrl);
+       if (ifm & (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE))
+               sc->pause = 1;
+
        sc->use_rss = mxge_use_rss;
 
        sc->throttle = mxge_throttle;
@@ -4236,7 +4240,10 @@ mxge_attach(device_t dev)
        sc->ifp = ifp;
        sc->dev = dev;
        if_initname(ifp, device_get_name(dev), device_get_unit(dev));
-       ifmedia_init(&sc->media, 0, mxge_media_change, mxge_media_status);
+
+       /* IFM_ETH_FORCEPAUSE can't be changed */
+       ifmedia_init(&sc->media, IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE,
+           mxge_media_change, mxge_media_status);
 
        lwkt_serialize_init(&sc->main_serialize);