#include "en.h"
 
-static void mlx5e_get_drvinfo(struct net_device *dev,
-                             struct ethtool_drvinfo *drvinfo)
+void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
+                              struct ethtool_drvinfo *drvinfo)
 {
-       struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5_core_dev *mdev = priv->mdev;
 
        strlcpy(drvinfo->driver, DRIVER_NAME, sizeof(drvinfo->driver));
                sizeof(drvinfo->bus_info));
 }
 
+static void mlx5e_get_drvinfo(struct net_device *dev,
+                             struct ethtool_drvinfo *drvinfo)
+{
+       struct mlx5e_priv *priv = netdev_priv(dev);
+
+       mlx5e_ethtool_get_drvinfo(priv, drvinfo);
+}
+
 struct ptys2ethtool_config {
        __ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
        __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised);
        ((mlx5e_query_global_pause_combined(priv) + hweight8(mlx5e_query_pfc_combined(priv))) * \
          NUM_PPORT_PER_PRIO_PFC_COUNTERS)
 
-static int mlx5e_get_sset_count(struct net_device *dev, int sset)
+int mlx5e_ethtool_get_sset_count(struct mlx5e_priv *priv, int sset)
 {
-       struct mlx5e_priv *priv = netdev_priv(dev);
 
        switch (sset) {
        case ETH_SS_STATS:
        }
 }
 
+static int mlx5e_get_sset_count(struct net_device *dev, int sset)
+{
+       struct mlx5e_priv *priv = netdev_priv(dev);
+
+       return mlx5e_ethtool_get_sset_count(priv, sset);
+}
+
 static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data)
 {
        int i, j, tc, prio, idx = 0;
                                        priv->channel_tc2txq[i][tc]);
 }
 
-static void mlx5e_get_strings(struct net_device *dev,
-                             uint32_t stringset, uint8_t *data)
+void mlx5e_ethtool_get_strings(struct mlx5e_priv *priv,
+                              uint32_t stringset, uint8_t *data)
 {
-       struct mlx5e_priv *priv = netdev_priv(dev);
        int i;
 
        switch (stringset) {
        }
 }
 
-static void mlx5e_get_ethtool_stats(struct net_device *dev,
-                                   struct ethtool_stats *stats, u64 *data)
+static void mlx5e_get_strings(struct net_device *dev,
+                             uint32_t stringset, uint8_t *data)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
+
+       mlx5e_ethtool_get_strings(priv, stringset, data);
+}
+
+void mlx5e_ethtool_get_ethtool_stats(struct mlx5e_priv *priv,
+                                    struct ethtool_stats *stats, u64 *data)
+{
        struct mlx5e_channels *channels;
        struct mlx5_priv *mlx5_priv;
        int i, j, tc, prio, idx = 0;
                                                                   sq_stats_desc, j);
 }
 
+static void mlx5e_get_ethtool_stats(struct net_device *dev,
+                                   struct ethtool_stats *stats,
+                                   u64 *data)
+{
+       struct mlx5e_priv *priv = netdev_priv(dev);
+
+       mlx5e_ethtool_get_ethtool_stats(priv, stats, data);
+}
+
 static u32 mlx5e_rx_wqes_to_packets(struct mlx5e_priv *priv, int rq_wq_type,
                                    int num_wqe)
 {
        return 1 << (order_base_2(num_wqes));
 }
 
-static void mlx5e_get_ringparam(struct net_device *dev,
-                               struct ethtool_ringparam *param)
+void mlx5e_ethtool_get_ringparam(struct mlx5e_priv *priv,
+                                struct ethtool_ringparam *param)
 {
-       struct mlx5e_priv *priv = netdev_priv(dev);
        int rq_wq_type = priv->channels.params.rq_wq_type;
 
        param->rx_max_pending = mlx5e_rx_wqes_to_packets(priv, rq_wq_type,
        param->tx_pending     = 1 << priv->channels.params.log_sq_size;
 }
 
-static int mlx5e_set_ringparam(struct net_device *dev,
-                              struct ethtool_ringparam *param)
+static void mlx5e_get_ringparam(struct net_device *dev,
+                               struct ethtool_ringparam *param)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
+
+       mlx5e_ethtool_get_ringparam(priv, param);
+}
+
+int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv,
+                               struct ethtool_ringparam *param)
+{
        int rq_wq_type = priv->channels.params.rq_wq_type;
        struct mlx5e_channels new_channels = {};
        u32 rx_pending_wqes;
        int err = 0;
 
        if (param->rx_jumbo_pending) {
-               netdev_info(dev, "%s: rx_jumbo_pending not supported\n",
+               netdev_info(priv->netdev, "%s: rx_jumbo_pending not supported\n",
                            __func__);
                return -EINVAL;
        }
        if (param->rx_mini_pending) {
-               netdev_info(dev, "%s: rx_mini_pending not supported\n",
+               netdev_info(priv->netdev, "%s: rx_mini_pending not supported\n",
                            __func__);
                return -EINVAL;
        }
                                                   param->rx_pending);
 
        if (param->rx_pending < min_rq_size) {
-               netdev_info(dev, "%s: rx_pending (%d) < min (%d)\n",
+               netdev_info(priv->netdev, "%s: rx_pending (%d) < min (%d)\n",
                            __func__, param->rx_pending,
                            min_rq_size);
                return -EINVAL;
        }
        if (param->rx_pending > max_rq_size) {
-               netdev_info(dev, "%s: rx_pending (%d) > max (%d)\n",
+               netdev_info(priv->netdev, "%s: rx_pending (%d) > max (%d)\n",
                            __func__, param->rx_pending,
                            max_rq_size);
                return -EINVAL;
        num_mtts = MLX5E_REQUIRED_MTTS(rx_pending_wqes);
        if (priv->channels.params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ &&
            !MLX5E_VALID_NUM_MTTS(num_mtts)) {
-               netdev_info(dev, "%s: rx_pending (%d) request can't be satisfied, try to reduce.\n",
+               netdev_info(priv->netdev, "%s: rx_pending (%d) request can't be satisfied, try to reduce.\n",
                            __func__, param->rx_pending);
                return -EINVAL;
        }
 
        if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
-               netdev_info(dev, "%s: tx_pending (%d) < min (%d)\n",
+               netdev_info(priv->netdev, "%s: tx_pending (%d) < min (%d)\n",
                            __func__, param->tx_pending,
                            1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
                return -EINVAL;
        }
        if (param->tx_pending > (1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE)) {
-               netdev_info(dev, "%s: tx_pending (%d) > max (%d)\n",
+               netdev_info(priv->netdev, "%s: tx_pending (%d) > max (%d)\n",
                            __func__, param->tx_pending,
                            1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE);
                return -EINVAL;
        return err;
 }
 
-static void mlx5e_get_channels(struct net_device *dev,
-                              struct ethtool_channels *ch)
+static int mlx5e_set_ringparam(struct net_device *dev,
+                              struct ethtool_ringparam *param)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
 
+       return mlx5e_ethtool_set_ringparam(priv, param);
+}
+
+void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv,
+                               struct ethtool_channels *ch)
+{
        ch->max_combined   = priv->profile->max_nch(priv->mdev);
        ch->combined_count = priv->channels.params.num_channels;
 }
 
-static int mlx5e_set_channels(struct net_device *dev,
-                             struct ethtool_channels *ch)
+static void mlx5e_get_channels(struct net_device *dev,
+                              struct ethtool_channels *ch)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
+
+       mlx5e_ethtool_get_channels(priv, ch);
+}
+
+int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
+                              struct ethtool_channels *ch)
+{
        unsigned int count = ch->combined_count;
        struct mlx5e_channels new_channels = {};
        bool arfs_enabled;
        int err = 0;
 
        if (!count) {
-               netdev_info(dev, "%s: combined_count=0 not supported\n",
+               netdev_info(priv->netdev, "%s: combined_count=0 not supported\n",
                            __func__);
                return -EINVAL;
        }
        if (err)
                goto out;
 
-       arfs_enabled = dev->features & NETIF_F_NTUPLE;
+       arfs_enabled = priv->netdev->features & NETIF_F_NTUPLE;
        if (arfs_enabled)
                mlx5e_arfs_disable(priv);
 
        if (arfs_enabled) {
                err = mlx5e_arfs_enable(priv);
                if (err)
-                       netdev_err(dev, "%s: mlx5e_arfs_enable failed: %d\n",
+                       netdev_err(priv->netdev, "%s: mlx5e_arfs_enable failed: %d\n",
                                   __func__, err);
        }
 
        return err;
 }
 
-static int mlx5e_get_coalesce(struct net_device *netdev,
-                             struct ethtool_coalesce *coal)
+static int mlx5e_set_channels(struct net_device *dev,
+                             struct ethtool_channels *ch)
 {
-       struct mlx5e_priv *priv = netdev_priv(netdev);
+       struct mlx5e_priv *priv = netdev_priv(dev);
+
+       return mlx5e_ethtool_set_channels(priv, ch);
+}
 
+int mlx5e_ethtool_get_coalesce(struct mlx5e_priv *priv,
+                              struct ethtool_coalesce *coal)
+{
        if (!MLX5_CAP_GEN(priv->mdev, cq_moderation))
                return -EOPNOTSUPP;
 
        return 0;
 }
 
+static int mlx5e_get_coalesce(struct net_device *netdev,
+                             struct ethtool_coalesce *coal)
+{
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+
+       return mlx5e_ethtool_get_coalesce(priv, coal);
+}
+
 static void
 mlx5e_set_priv_channels_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
 {
        }
 }
 
-static int mlx5e_set_coalesce(struct net_device *netdev,
-                             struct ethtool_coalesce *coal)
+int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv,
+                              struct ethtool_coalesce *coal)
 {
-       struct mlx5e_priv *priv    = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5e_channels new_channels = {};
        int err = 0;
        return err;
 }
 
+static int mlx5e_set_coalesce(struct net_device *netdev,
+                             struct ethtool_coalesce *coal)
+{
+       struct mlx5e_priv *priv    = netdev_priv(netdev);
+
+       return mlx5e_ethtool_set_coalesce(priv, coal);
+}
+
 static void ptys2ethtool_supported_link(unsigned long *supported_modes,
                                        u32 eth_proto_cap)
 {
 
--- /dev/null
+/*
+ * Copyright (c) 2017, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "en.h"
+#include "ipoib.h"
+
+static void mlx5i_get_drvinfo(struct net_device *dev,
+                             struct ethtool_drvinfo *drvinfo)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(dev);
+
+       mlx5e_ethtool_get_drvinfo(priv, drvinfo);
+}
+
+static void mlx5i_get_strings(struct net_device *dev,
+                             uint32_t stringset, uint8_t *data)
+{
+       struct mlx5e_priv *priv  = mlx5i_epriv(dev);
+
+       mlx5e_ethtool_get_strings(priv, stringset, data);
+}
+
+static int mlx5i_get_sset_count(struct net_device *dev, int sset)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(dev);
+
+       return mlx5e_ethtool_get_sset_count(priv, sset);
+}
+
+static void mlx5i_get_ethtool_stats(struct net_device *dev,
+                                   struct ethtool_stats *stats,
+                                   u64 *data)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(dev);
+
+       mlx5e_ethtool_get_ethtool_stats(priv, stats, data);
+}
+
+static int mlx5i_set_ringparam(struct net_device *dev,
+                              struct ethtool_ringparam *param)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(dev);
+
+       return mlx5e_ethtool_set_ringparam(priv, param);
+}
+
+static void mlx5i_get_ringparam(struct net_device *dev,
+                               struct ethtool_ringparam *param)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(dev);
+
+       mlx5e_ethtool_get_ringparam(priv, param);
+}
+
+static int mlx5i_set_channels(struct net_device *dev,
+                             struct ethtool_channels *ch)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(dev);
+
+       return mlx5e_ethtool_set_channels(priv, ch);
+}
+
+static void mlx5i_get_channels(struct net_device *dev,
+                              struct ethtool_channels *ch)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(dev);
+
+       mlx5e_ethtool_get_channels(priv, ch);
+}
+
+static int mlx5i_set_coalesce(struct net_device *netdev,
+                             struct ethtool_coalesce *coal)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(netdev);
+
+       return mlx5e_ethtool_set_coalesce(priv, coal);
+}
+
+static int mlx5i_get_coalesce(struct net_device *netdev,
+                             struct ethtool_coalesce *coal)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(netdev);
+
+       return mlx5e_ethtool_get_coalesce(priv, coal);
+}
+
+const struct ethtool_ops mlx5i_ethtool_ops = {
+       .get_drvinfo       = mlx5i_get_drvinfo,
+       .get_strings       = mlx5i_get_strings,
+       .get_sset_count    = mlx5i_get_sset_count,
+       .get_ethtool_stats = mlx5i_get_ethtool_stats,
+       .get_ringparam     = mlx5i_get_ringparam,
+       .set_ringparam     = mlx5i_set_ringparam,
+       .get_channels      = mlx5i_get_channels,
+       .set_channels      = mlx5i_set_channels,
+       .get_coalesce      = mlx5i_get_coalesce,
+       .set_coalesce      = mlx5i_set_coalesce,
+};