ig: Factor out functions for flow control
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 20 Nov 2015 07:34:52 +0000 (15:34 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 20 Nov 2015 08:12:27 +0000 (16:12 +0800)
sys/dev/netif/em/if_em.c
sys/dev/netif/emx/if_emx.c
sys/dev/netif/ig_hal/e1000_dragonfly.h [new file with mode: 0644]
sys/dev/netif/ig_hal/e1000_osdep.c
sys/dev/netif/igb/if_igb.c

index 5cf0cd7..ca73ca4 100644 (file)
 
 #include <dev/netif/ig_hal/e1000_api.h>
 #include <dev/netif/ig_hal/e1000_82571.h>
+#include <dev/netif/ig_hal/e1000_dragonfly.h>
 #include <dev/netif/em/if_em.h>
 
 #define DEBUG_HW 0
 
-#define EM_FLOWCTRL_STRLEN     16
-
 #define EM_NAME        "Intel(R) PRO/1000 Network Connection "
 #define EM_VER " 7.4.2"
 
@@ -313,8 +312,6 @@ static void em_update_link_status(struct adapter *);
 static void    em_smartspeed(struct adapter *);
 static void    em_set_itr(struct adapter *, uint32_t);
 static void    em_disable_aspm(struct adapter *);
-static enum e1000_fc_mode em_str2fc(const char *);
-static void    em_fc2str(enum e1000_fc_mode, char *, int);
 
 /* Hardware workarounds */
 static int     em_82547_fifo_workaround(struct adapter *, int);
@@ -379,7 +376,7 @@ static int  em_debug_sbp = FALSE;
 static int     em_82573_workaround = 1;
 static int     em_msi_enable = 1;
 
-static char    em_flowctrl[EM_FLOWCTRL_STRLEN] = "rx_pause";
+static char    em_flowctrl[E1000_FC_STRLEN] = E1000_FC_STR_RX_PAUSE;
 
 TUNABLE_INT("hw.em.int_throttle_ceil", &em_int_throttle_ceil);
 TUNABLE_INT("hw.em.rxd", &em_rxd);
@@ -435,7 +432,7 @@ em_attach(device_t dev)
        int error = 0;
        uint16_t eeprom_data, device_id, apme_mask;
        driver_intr_t *intr_func;
-       char flowctrl[EM_FLOWCTRL_STRLEN];
+       char flowctrl[E1000_FC_STRLEN];
 
        adapter->dev = adapter->osdep.dev = dev;
 
@@ -797,7 +794,7 @@ em_attach(device_t dev)
        /* Setup flow control. */
        device_getenv_string(dev, "flow_ctrl", flowctrl, sizeof(flowctrl),
            em_flowctrl);
-       adapter->flow_ctrl = em_str2fc(flowctrl);
+       adapter->flow_ctrl = e1000_str2fc(flowctrl);
        if (adapter->hw.mac.type == e1000_pchlan) {
                /* Only pause reception is supported */
                adapter->flow_ctrl = e1000_fc_rx_pause;
@@ -4139,7 +4136,11 @@ em_add_sysctl(struct adapter *adapter)
        SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
            OID_AUTO, "flow_ctrl", CTLTYPE_STRING|access, adapter, 0,
            em_sysctl_flowctrl, "A",
-           "flow control: full, rx_pause, tx_pause, none");
+           "flow control: "
+           E1000_FC_STR_FULL ", "
+           E1000_FC_STR_RX_PAUSE ", "
+           E1000_FC_STR_TX_PAUSE ", "
+           E1000_FC_STR_NONE);
 }
 
 static int
@@ -4426,69 +4427,11 @@ em_tso_setup(struct adapter *adapter, struct mbuf *mp,
        return 1;
 }
 
-static enum e1000_fc_mode
-em_str2fc(const char *str)
-{
-       if (strcmp(str, "none") == 0)
-               return e1000_fc_none;
-       else if (strcmp(str, "rx_pause") == 0)
-               return e1000_fc_rx_pause;
-       else if (strcmp(str, "tx_pause") == 0)
-               return e1000_fc_tx_pause;
-       else
-               return e1000_fc_full;
-}
-
-static void
-em_fc2str(enum e1000_fc_mode fc, char *str, int len)
-{
-       const char *fc_str = "full";
-
-       switch (fc) {
-       case e1000_fc_none:
-               fc_str = "none";
-               break;
-
-       case e1000_fc_rx_pause:
-               fc_str = "rx_pause";
-               break;
-
-       case e1000_fc_tx_pause:
-               fc_str = "tx_pause";
-               break;
-
-       default:
-               break;
-       }
-       strlcpy(str, fc_str, len);
-}
-
 static int
 em_sysctl_flowctrl(SYSCTL_HANDLER_ARGS)
 {
        struct adapter *adapter = arg1;
-       struct ifnet *ifp = &adapter->arpcom.ac_if;
-       char flowctrl[EM_FLOWCTRL_STRLEN];
-       enum e1000_fc_mode fc;
-       int error;
 
-       em_fc2str(adapter->flow_ctrl, flowctrl, sizeof(flowctrl));
-       error = sysctl_handle_string(oidp, flowctrl, sizeof(flowctrl), req);
-       if (error != 0 || req->newptr == NULL)
-               return error;
-
-       fc = em_str2fc(flowctrl);
-
-       ifnet_serialize_all(ifp);
-       if (fc == adapter->flow_ctrl)
-               goto done;
-
-       adapter->flow_ctrl = fc;
-       adapter->hw.fc.requested_mode = adapter->flow_ctrl;
-       adapter->hw.fc.current_mode = adapter->flow_ctrl;
-       e1000_force_mac_fc(&adapter->hw);
-done:
-       ifnet_deserialize_all(ifp);
-
-       return 0;
+       return e1000_sysctl_flowctrl(&adapter->arpcom.ac_if,
+           &adapter->flow_ctrl, &adapter->hw, oidp, req);
 }
index ffb11b4..250ec0d 100644 (file)
 
 #include <dev/netif/ig_hal/e1000_api.h>
 #include <dev/netif/ig_hal/e1000_82571.h>
+#include <dev/netif/ig_hal/e1000_dragonfly.h>
 #include <dev/netif/emx/if_emx.h>
 
 #define DEBUG_HW 0
 
-#define EMX_FLOWCTRL_STRLEN    16
-
 #ifdef EMX_RSS_DEBUG
 #define EMX_RSS_DPRINTF(sc, lvl, fmt, ...) \
 do { \
@@ -247,8 +246,6 @@ static void emx_update_link_status(struct emx_softc *);
 static void    emx_smartspeed(struct emx_softc *);
 static void    emx_set_itr(struct emx_softc *, uint32_t);
 static void    emx_disable_aspm(struct emx_softc *);
-static enum e1000_fc_mode emx_str2fc(const char *);
-static void    emx_fc2str(enum e1000_fc_mode, char *, int);
 
 static void    emx_print_debug_info(struct emx_softc *);
 static void    emx_print_nvm_info(struct emx_softc *);
@@ -315,7 +312,7 @@ static int  emx_debug_sbp = 0;
 static int     emx_82573_workaround = 1;
 static int     emx_msi_enable = 1;
 
-static char    emx_flowctrl[EMX_FLOWCTRL_STRLEN] = "rx_pause";
+static char    emx_flowctrl[E1000_FC_STRLEN] = E1000_FC_STR_RX_PAUSE;
 
 TUNABLE_INT("hw.emx.int_throttle_ceil", &emx_int_throttle_ceil);
 TUNABLE_INT("hw.emx.rxd", &emx_rxd);
@@ -439,7 +436,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[EMX_FLOWCTRL_STRLEN];
+       char flowctrl[E1000_FC_STRLEN];
 #ifdef IFPOLL_ENABLE
        int offset, offset_def;
 #endif
@@ -837,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 = emx_str2fc(flowctrl);
+       sc->flow_ctrl = e1000_str2fc(flowctrl);
 
        /* Setup OS specific network interface */
        emx_setup_ifp(sc);
@@ -3710,10 +3707,14 @@ 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),
+       SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
            OID_AUTO, "flow_ctrl", CTLTYPE_STRING|CTLFLAG_RW, sc, 0,
            emx_sysctl_flowctrl, "A",
-           "flow control: full, rx_pause, tx_pause, none");
+           "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),
@@ -4344,69 +4345,11 @@ emx_get_txring_inuse(const struct emx_softc *sc, boolean_t polling)
                return 1;
 }
 
-static enum e1000_fc_mode
-emx_str2fc(const char *str)
-{
-       if (strcmp(str, "none") == 0)
-               return e1000_fc_none;
-       else if (strcmp(str, "rx_pause") == 0)
-               return e1000_fc_rx_pause;
-       else if (strcmp(str, "tx_pause") == 0)
-               return e1000_fc_tx_pause;
-       else
-               return e1000_fc_full;
-}
-
-static void
-emx_fc2str(enum e1000_fc_mode fc, char *str, int len)
-{
-       const char *fc_str = "full";
-
-       switch (fc) {
-       case e1000_fc_none:
-               fc_str = "none";
-               break;
-
-       case e1000_fc_rx_pause:
-               fc_str = "rx_pause";
-               break;
-
-       case e1000_fc_tx_pause:
-               fc_str = "tx_pause";
-               break;
-
-       default:
-               break;
-       }
-       strlcpy(str, fc_str, len);
-}
-
 static int
 emx_sysctl_flowctrl(SYSCTL_HANDLER_ARGS)
 {
        struct emx_softc *sc = arg1;
-       struct ifnet *ifp = &sc->arpcom.ac_if;
-       char flowctrl[EMX_FLOWCTRL_STRLEN];
-       enum e1000_fc_mode fc;
-       int error;
-
-       emx_fc2str(sc->flow_ctrl, flowctrl, sizeof(flowctrl));
-       error = sysctl_handle_string(oidp, flowctrl, sizeof(flowctrl), req);
-       if (error != 0 || req->newptr == NULL)
-               return error;
 
-       fc = emx_str2fc(flowctrl);
-
-       ifnet_serialize_all(ifp);
-       if (fc == sc->flow_ctrl)
-               goto done;
-
-       sc->flow_ctrl = fc;
-       sc->hw.fc.requested_mode = sc->flow_ctrl;
-       sc->hw.fc.current_mode = sc->flow_ctrl;
-       e1000_force_mac_fc(&sc->hw);
-done:
-       ifnet_deserialize_all(ifp);
-
-       return 0;
+       return e1000_sysctl_flowctrl(&sc->arpcom.ac_if, &sc->flow_ctrl, &sc->hw,
+           oidp, req);
 }
diff --git a/sys/dev/netif/ig_hal/e1000_dragonfly.h b/sys/dev/netif/ig_hal/e1000_dragonfly.h
new file mode 100644 (file)
index 0000000..cd98f4a
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Sepherosa Ziehau <sepherosa@gmail.com>
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#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);
+
+#endif /* !_E1000_DRAGONFLY_H_ */
index 61074c8..84937c5 100644 (file)
 
 ******************************************************************************/
 
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <net/if_var.h>
+
 #include "e1000_api.h"
+#include "e1000_dragonfly.h"
 
 /*
  * NOTE: the following routines using the e1000 
@@ -96,6 +101,72 @@ 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;
+
+       switch (fc) {
+       case e1000_fc_none:
+               fc_str = E1000_FC_STR_NONE;
+               break;
+
+       case e1000_fc_rx_pause:
+               fc_str = E1000_FC_STR_RX_PAUSE;
+               break;
+
+       case e1000_fc_tx_pause:
+               fc_str = E1000_FC_STR_TX_PAUSE;
+               break;
+
+       default:
+               break;
+       }
+       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;
+}
+
 /* Module glue */
 static moduledata_t ig_hal_mod = { "ig_hal" };
 DECLARE_MODULE(ig_hal, ig_hal_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
index a821d86..accc235 100644 (file)
 
 #include <dev/netif/ig_hal/e1000_api.h>
 #include <dev/netif/ig_hal/e1000_82575.h>
+#include <dev/netif/ig_hal/e1000_dragonfly.h>
 #include <dev/netif/igb/if_igb.h>
 
-#define IGB_FLOWCTRL_STRLEN    16
-
 #ifdef IGB_RSS_DEBUG
 #define IGB_RSS_DPRINTF(sc, lvl, fmt, ...) \
 do { \
@@ -164,8 +163,6 @@ static int  igb_sysctl_npoll_rxoff(SYSCTL_HANDLER_ARGS);
 static int     igb_sysctl_npoll_txoff(SYSCTL_HANDLER_ARGS);
 #endif
 static int     igb_sysctl_flowctrl(SYSCTL_HANDLER_ARGS);
-static enum e1000_fc_mode igb_str2fc(const char *);
-static void    igb_fc2str(enum e1000_fc_mode, char *, int);
 
 static void    igb_vf_init_stats(struct igb_softc *);
 static void    igb_reset(struct igb_softc *);
@@ -282,7 +279,7 @@ static int  igb_msi_enable = 1;
 static int     igb_msix_enable = 1;
 static int     igb_eee_disabled = 1;   /* Energy Efficient Ethernet */
 
-static char    igb_flowctrl[IGB_FLOWCTRL_STRLEN] = "rx_pause";
+static char    igb_flowctrl[E1000_FC_STRLEN] = E1000_FC_STR_RX_PAUSE;
 
 /*
  * DMA Coalescing, only for i350 - default to off,
@@ -379,7 +376,7 @@ igb_attach(device_t dev)
        struct igb_softc *sc = device_get_softc(dev);
        uint16_t eeprom_data;
        int error = 0, ring_max;
-       char flowctrl[IGB_FLOWCTRL_STRLEN];
+       char flowctrl[E1000_FC_STRLEN];
 #ifdef IFPOLL_ENABLE
        int offset, offset_def;
 #endif
@@ -476,7 +473,7 @@ igb_attach(device_t dev)
        /* Setup flow control. */
        device_getenv_string(dev, "flow_ctrl", flowctrl, sizeof(flowctrl),
            igb_flowctrl);
-       sc->flow_ctrl = igb_str2fc(flowctrl);
+       sc->flow_ctrl = e1000_str2fc(flowctrl);
 
        /* Enable bus mastering */
        pci_enable_busmaster(dev);
@@ -1289,33 +1286,18 @@ igb_update_link_status(struct igb_softc *sc)
                e1000_get_speed_and_duplex(hw, 
                    &sc->link_speed, &sc->link_duplex);
                if (bootverbose) {
-                       const char *flowctl;
+                       char flowctrl[E1000_FC_STRLEN];
 
                        /* Get the flow control for display */
-                       switch (hw->fc.current_mode) {
-                       case e1000_fc_rx_pause:
-                               flowctl = "RX";
-                               break;
-
-                       case e1000_fc_tx_pause:
-                               flowctl = "TX";
-                               break;
-
-                       case e1000_fc_full:
-                               flowctl = "Full";
-                               break;
-
-                       default:
-                               flowctl = "None";
-                               break;
-                       }
+                       e1000_fc2str(hw->fc.current_mode, flowctrl,
+                           sizeof(flowctrl));
 
                        if_printf(ifp, "Link is up %d Mbps %s, "
                            "Flow control: %s\n",
                            sc->link_speed,
                            sc->link_duplex == FULL_DUPLEX ?
                            "Full Duplex" : "Half Duplex",
-                           flowctl);
+                           flowctrl);
                }
                sc->link_active = 1;
 
@@ -1694,7 +1676,11 @@ igb_add_sysctl(struct igb_softc *sc)
        SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree),
            OID_AUTO, "flow_ctrl", CTLTYPE_STRING|CTLFLAG_RW, sc, 0,
            igb_sysctl_flowctrl, "A",
-           "flow control: full, rx_pause, tx_pause, none");
+           "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),
@@ -4952,69 +4938,11 @@ igb_set_timer_cpuid(struct igb_softc *sc, boolean_t polling)
                sc->timer_cpuid = rman_get_cpuid(sc->intr_res);
 }
 
-static enum e1000_fc_mode
-igb_str2fc(const char *str)
-{
-       if (strcmp(str, "none") == 0)
-               return e1000_fc_none;
-       else if (strcmp(str, "rx_pause") == 0)
-               return e1000_fc_rx_pause;
-       else if (strcmp(str, "tx_pause") == 0)
-               return e1000_fc_tx_pause;
-       else
-               return e1000_fc_full;
-}
-
-static void
-igb_fc2str(enum e1000_fc_mode fc, char *str, int len)
-{
-       const char *fc_str = "full";
-
-       switch (fc) {
-       case e1000_fc_none:
-               fc_str = "none";
-               break;
-
-       case e1000_fc_rx_pause:
-               fc_str = "rx_pause";
-               break;
-
-       case e1000_fc_tx_pause:
-               fc_str = "tx_pause";
-               break;
-
-       default:
-               break;
-       }
-       strlcpy(str, fc_str, len);
-}
-
 static int
 igb_sysctl_flowctrl(SYSCTL_HANDLER_ARGS)
 {
        struct igb_softc *sc = arg1;
-       struct ifnet *ifp = &sc->arpcom.ac_if;
-       char flowctrl[IGB_FLOWCTRL_STRLEN];
-       enum e1000_fc_mode fc;
-       int error;
 
-       igb_fc2str(sc->flow_ctrl, flowctrl, sizeof(flowctrl));
-       error = sysctl_handle_string(oidp, flowctrl, sizeof(flowctrl), req);
-       if (error != 0 || req->newptr == NULL)
-               return error;
-
-       fc = igb_str2fc(flowctrl);
-
-       ifnet_serialize_all(ifp);
-       if (fc == sc->flow_ctrl)
-               goto done;
-
-       sc->flow_ctrl = fc;
-       sc->hw.fc.requested_mode = sc->flow_ctrl;
-       sc->hw.fc.current_mode = sc->flow_ctrl;
-       e1000_force_mac_fc(&sc->hw);
-done:
-       ifnet_deserialize_all(ifp);
-
-       return 0;
+       return e1000_sysctl_flowctrl(&sc->arpcom.ac_if, &sc->flow_ctrl, &sc->hw,
+           oidp, req);
 }