]> git.openfabrics.org - ~aditr/compat-rdma.git/commitdiff
Added support for SLES12 SP3
authorVladimir Sokolovsky <vlad@mellanox.com>
Wed, 8 Aug 2018 20:23:18 +0000 (15:23 -0500)
committerVladimir Sokolovsky <vlad@mellanox.com>
Wed, 8 Aug 2018 20:23:25 +0000 (15:23 -0500)
The following backports were updated to support SLES12 SP3:
    IB core
    IPOIB
    MLX4
    MLX5

Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
patches/0002-BACKPORT-ib_core.patch
patches/0003-BACKPORT-ipoib.patch
patches/0004-BACKPORT-mlx5.patch
patches/0005-BACKPORT-mlx4.patch

index c480569fecf15c700ef0390c93793c8cc70782c7..5cafe9c43b01ff23afb00c7543babe782deddb4c 100644 (file)
@@ -6,7 +6,7 @@ Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
  drivers/infiniband/core/addr.c          |  18 +++-
  drivers/infiniband/core/cma.c           |  27 ++++++
  drivers/infiniband/core/cma_configfs.c  |  93 ++++++++++++++++++++
- drivers/infiniband/core/core_priv.h     |   9 ++
+ drivers/infiniband/core/core_priv.h     |  36 ++++++++
  drivers/infiniband/core/cq.c            |  35 +++++++-
  drivers/infiniband/core/device.c        |  32 +++++++
  drivers/infiniband/core/fmr_pool.c      |  55 ++++++++++++
@@ -14,7 +14,7 @@ Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
  drivers/infiniband/core/netlink.c       |  29 +++++++
  drivers/infiniband/core/nldev.c         |  30 +++++++
  drivers/infiniband/core/restrack.c      |   4 +
- drivers/infiniband/core/roce_gid_mgmt.c |  31 +++++++
+ drivers/infiniband/core/roce_gid_mgmt.c |  59 +++++++++++++
  drivers/infiniband/core/sa_query.c      |  47 ++++++++++
  drivers/infiniband/core/ucm.c           |  16 ++++
  drivers/infiniband/core/ucma.c          |  15 ++++
@@ -26,7 +26,7 @@ Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
  include/rdma/ib_verbs.h                 | 147 ++++++++++++++++++++++++++++++++
  include/rdma/rdma_netlink.h             |   4 +
  include/rdma/restrack.h                 |   3 +
- 23 files changed, 713 insertions(+), 2 deletions(-)
+ 23 files changed, 768 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
 index xxxxxxx..xxxxxxx xxxxxx
@@ -343,7 +343,42 @@ diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_
 index xxxxxxx..xxxxxxx xxxxxx
 --- a/drivers/infiniband/core/core_priv.h
 +++ b/drivers/infiniband/core/core_priv.h
-@@ -194,6 +194,7 @@ void ib_sa_cleanup(void);
+@@ -179,7 +179,34 @@ static inline void ib_rdmacg_uncharge(struct ib_rdmacg_object *cg_obj,
+ static inline bool rdma_is_upper_dev_rcu(struct net_device *dev,
+                                        struct net_device *upper)
+ {
++#if defined(HAVE_NETDEV_HAS_UPPER_DEV_ALL_RCU)
+       return netdev_has_upper_dev_all_rcu(dev, upper);
++#elif defined(HAVE_NETDEV_FOR_EACH_ALL_UPPER_DEV_RCU)
++      struct net_device *_upper = NULL;
++      struct list_head *iter;
++
++      netdev_for_each_all_upper_dev_rcu(dev, _upper, iter)
++              if (_upper == upper)
++                      break;
++
++      return _upper == upper;
++#else
++      struct net_device *rdev_upper;
++      struct net_device *master;
++      bool ret;
++
++      if (!upper || !dev)
++              ret = false;
++
++      rdev_upper = rdma_vlan_dev_real_dev(upper);
++      master = netdev_master_upper_dev_get_rcu(dev);
++
++      ret = (upper == master) ||
++            (rdev_upper && (rdev_upper == master)) ||
++            (rdev_upper == dev);
++
++      return ret;
++#endif
+ }
+ int addr_init(void);
+@@ -194,6 +221,7 @@ void ib_sa_cleanup(void);
  int rdma_nl_init(void);
  void rdma_nl_exit(void);
  
@@ -351,7 +386,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  int ib_nl_handle_resolve_resp(struct sk_buff *skb,
                              struct nlmsghdr *nlh,
                              struct netlink_ext_ack *extack);
-@@ -203,6 +204,14 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb,
+@@ -203,6 +231,14 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb,
  int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
                             struct nlmsghdr *nlh,
                             struct netlink_ext_ack *extack);
@@ -936,15 +971,64 @@ index xxxxxxx..xxxxxxx xxxxxx
        rtnl_unlock();
  }
  
-@@ -459,6 +468,7 @@ static int netdev_upper_walk(struct net_device *upper, void *data)
+@@ -439,6 +448,7 @@ static void callback_for_addr_gid_device_scan(struct ib_device *device,
+                         &parsed->gid_attr);
+ }
++#ifdef HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU
+ struct upper_list {
+       struct list_head list;
+       struct net_device *upper;
+@@ -458,7 +468,9 @@ static int netdev_upper_walk(struct net_device *upper, void *data)
        return 0;
  }
++#endif /* HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU */
  
 +#ifdef HAVE_NETDEV_NOTIFIER_CHANGEUPPER_INFO
  static void handle_netdev_upper(struct ib_device *ib_dev, u8 port,
                                void *cookie,
                                void (*handle_netdev)(struct ib_device *ib_dev,
-@@ -501,6 +511,7 @@ static void add_netdev_upper_ips(struct ib_device *ib_dev, u8 port,
+@@ -466,12 +478,38 @@ static void handle_netdev_upper(struct ib_device *ib_dev, u8 port,
+                                                     struct net_device *ndev))
+ {
+       struct net_device *ndev = cookie;
++#ifndef HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU
++      struct upper_list {
++              struct list_head list;
++              struct net_device *upper;
++      };
++      struct net_device *upper;
++#endif /* HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU */
+       struct upper_list *upper_iter;
+       struct upper_list *upper_temp;
+       LIST_HEAD(upper_list);
+       rcu_read_lock();
++#ifndef HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU
++      for_each_netdev(dev_net(ndev), upper) {
++              struct upper_list *entry;
++
++              if (!rdma_is_upper_dev_rcu(ndev, upper))
++                      continue;
++
++              entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
++              if (!entry) {
++                      pr_info("roce_gid_mgmt: couldn't allocate entry to delete ndev\n");
++                      continue;
++              }
++
++              list_add_tail(&entry->list, &upper_list);
++              dev_hold(upper);
++              entry->upper = upper;
++      }
++#else /* HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU */
+       netdev_walk_all_upper_dev_rcu(ndev, netdev_upper_walk, &upper_list);
++#endif /* HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU */
+       rcu_read_unlock();
+       handle_netdev(ib_dev, port, ndev);
+@@ -501,6 +539,7 @@ static void add_netdev_upper_ips(struct ib_device *ib_dev, u8 port,
  {
        handle_netdev_upper(ib_dev, port, cookie, _add_netdev_ips);
  }
@@ -952,7 +1036,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static void del_netdev_default_ips_join(struct ib_device *ib_dev, u8 port,
                                        struct net_device *rdma_ndev,
-@@ -578,6 +589,8 @@ static int netdevice_queue_work(struct netdev_event_work_cmd *cmds,
+@@ -578,6 +617,8 @@ static int netdevice_queue_work(struct netdev_event_work_cmd *cmds,
  
  static const struct netdev_event_work_cmd add_cmd = {
        .cb = add_netdev_ips, .filter = is_eth_port_of_netdev};
@@ -961,7 +1045,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static const struct netdev_event_work_cmd add_cmd_upper_ips = {
        .cb = add_netdev_upper_ips, .filter = is_eth_port_of_netdev};
  
-@@ -601,10 +614,15 @@ static void netdevice_event_changeupper(struct netdev_notifier_changeupper_info
+@@ -601,10 +642,15 @@ static void netdevice_event_changeupper(struct netdev_notifier_changeupper_info
                cmds[1].filter_ndev = changeupper_info->upper_dev;
        }
  }
@@ -977,7 +1061,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        static const struct netdev_event_work_cmd del_cmd = {
                .cb = del_netdev_ips, .filter = pass_all_filter};
        static const struct netdev_event_work_cmd bonding_default_del_cmd_join = {
-@@ -612,7 +630,11 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,
+@@ -612,7 +658,11 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,
        static const struct netdev_event_work_cmd default_del_cmd = {
                .cb = del_netdev_default_ips, .filter = pass_all_filter};
        static const struct netdev_event_work_cmd bonding_event_ips_del_cmd = {
@@ -989,7 +1073,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
        struct netdev_event_work_cmd cmds[ROCE_NETDEV_CALLBACK_SZ] = { {NULL} };
  
-@@ -622,6 +644,9 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,
+@@ -622,6 +672,9 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,
        switch (event) {
        case NETDEV_REGISTER:
        case NETDEV_UP:
@@ -999,7 +1083,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                cmds[0] = bonding_default_del_cmd_join;
                cmds[1] = add_cmd;
                break;
-@@ -638,16 +663,22 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,
+@@ -638,16 +691,22 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,
                cmds[1] = add_cmd;
                break;
  
index b1645a80183d5a292666d7ea07fa15e78bbfea29..d99fc865a849f5de44e33abec9611f708e14c0ac 100644 (file)
@@ -3,9 +3,9 @@ Subject: [PATCH] BACKPORT: ipoib
 
 Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
 ---
- drivers/infiniband/ulp/ipoib/ipoib_main.c    | 101 ++++++++++++++++++++++++++-
- drivers/infiniband/ulp/ipoib/ipoib_netlink.c |  31 +++++++-
- 2 files changed, 128 insertions(+), 4 deletions(-)
+ drivers/infiniband/ulp/ipoib/ipoib_main.c    | 117 ++++++++++++++++++++++++++-
+ drivers/infiniband/ulp/ipoib/ipoib_netlink.c |  31 ++++++-
+ 2 files changed, 144 insertions(+), 4 deletions(-)
 
 diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
 index xxxxxxx..xxxxxxx xxxxxx
@@ -112,7 +112,52 @@ index xxxxxxx..xxxxxxx xxxxxx
                in_dev_put(in_dev);
                if (ret_addr)
                        return true;
-@@ -707,7 +757,7 @@ static void push_pseudo_header(struct sk_buff *skb, const char *daddr)
+@@ -350,6 +400,7 @@ struct ipoib_walk_data {
+       struct net_device *result;
+ };
++#ifdef HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU
+ static int ipoib_upper_walk(struct net_device *upper, void *_data)
+ {
+       struct ipoib_walk_data *data = _data;
+@@ -363,6 +414,7 @@ static int ipoib_upper_walk(struct net_device *upper, void *_data)
+       return ret;
+ }
++#endif
+ /**
+  * Find a net_device matching the given address, which is an upper device of
+@@ -379,6 +431,9 @@ static struct net_device *ipoib_get_net_dev_match_addr(
+       struct ipoib_walk_data data = {
+               .addr = addr,
+       };
++#ifndef HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU
++      struct net_device *upper;
++#endif
+       rcu_read_lock();
+       if (ipoib_is_dev_match_addr_rcu(addr, dev)) {
+@@ -387,7 +442,18 @@ static struct net_device *ipoib_get_net_dev_match_addr(
+               goto out;
+       }
++#ifdef HAVE_NETDEV_WALK_ALL_UPPER_DEV_RCU
+       netdev_walk_all_upper_dev_rcu(dev, ipoib_upper_walk, &data);
++#else
++      for_each_netdev(&init_net, upper) {
++                if (ipoib_is_dev_match_addr_rcu(addr, upper)) {
++                        dev_hold(upper);
++                        data.result = upper;
++                        break;
++                }
++        }
++#endif
++
+ out:
+       rcu_read_unlock();
+       return data.result;
+@@ -707,7 +773,7 @@ static void push_pseudo_header(struct sk_buff *skb, const char *daddr)
  {
        struct ipoib_pseudo_header *phdr;
  
@@ -121,7 +166,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
  }
  
-@@ -1202,7 +1252,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
+@@ -1202,7 +1268,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
  {
        struct ipoib_header *header;
  
@@ -130,7 +175,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        header->proto = htons(type);
        header->reserved = 0;
-@@ -1868,6 +1918,7 @@ static int ipoib_get_vf_config(struct net_device *dev, int vf,
+@@ -1868,6 +1934,7 @@ static int ipoib_get_vf_config(struct net_device *dev, int vf,
        return 0;
  }
  
@@ -138,7 +183,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int ipoib_set_vf_guid(struct net_device *dev, int vf, u64 guid, int type)
  {
        struct ipoib_dev_priv *priv = ipoib_priv(dev);
-@@ -1877,6 +1928,7 @@ static int ipoib_set_vf_guid(struct net_device *dev, int vf, u64 guid, int type)
+@@ -1877,6 +1944,7 @@ static int ipoib_set_vf_guid(struct net_device *dev, int vf, u64 guid, int type)
  
        return ib_set_vf_guid(priv->ca, vf, priv->port, guid, type);
  }
@@ -146,7 +191,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static int ipoib_get_vf_stats(struct net_device *dev, int vf,
                              struct ifla_vf_stats *vf_stats)
-@@ -1894,7 +1946,11 @@ static const struct net_device_ops ipoib_netdev_ops_pf = {
+@@ -1894,7 +1962,11 @@ static const struct net_device_ops ipoib_netdev_ops_pf = {
        .ndo_uninit              = ipoib_uninit,
        .ndo_open                = ipoib_open,
        .ndo_stop                = ipoib_stop,
@@ -158,7 +203,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        .ndo_fix_features        = ipoib_fix_features,
        .ndo_start_xmit          = ipoib_start_xmit,
        .ndo_tx_timeout          = ipoib_timeout,
-@@ -1903,24 +1959,46 @@ static const struct net_device_ops ipoib_netdev_ops_pf = {
+@@ -1903,24 +1975,46 @@ static const struct net_device_ops ipoib_netdev_ops_pf = {
        .ndo_set_vf_link_state   = ipoib_set_vf_link_state,
        .ndo_get_vf_config       = ipoib_get_vf_config,
        .ndo_get_vf_stats        = ipoib_get_vf_stats,
@@ -205,7 +250,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  };
  
  void ipoib_setup_common(struct net_device *dev)
-@@ -1985,9 +2063,16 @@ static struct net_device
+@@ -1985,9 +2079,16 @@ static struct net_device
        struct net_device *dev;
        struct rdma_netdev *rn;
  
@@ -222,7 +267,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (!dev)
                return NULL;
  
-@@ -2012,14 +2097,22 @@ static struct net_device *ipoib_get_netdev(struct ib_device *hca, u8 port,
+@@ -2012,14 +2113,22 @@ static struct net_device *ipoib_get_netdev(struct ib_device *hca, u8 port,
        if (hca->alloc_rdma_netdev) {
                dev = hca->alloc_rdma_netdev(hca, port,
                                             RDMA_NETDEV_IPOIB, name,
@@ -245,7 +290,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                                                  ipoib_setup_common);
  
        return dev;
-@@ -2262,7 +2355,9 @@ static struct net_device *ipoib_add_port(const char *format,
+@@ -2262,7 +2371,9 @@ static struct net_device *ipoib_add_port(const char *format,
        /* MTU will be reset when mcast join happens */
        priv->dev->mtu  = IPOIB_UD_MTU(priv->max_ib_mtu);
        priv->mcast_mtu  = priv->admin_mtu = priv->dev->mtu;
index 0d61d7a0d805f8e79c2dac2bd1ecfc880b72312a..2c4ab2e359d7c1e973498c56cd6132197f2d23d9 100644 (file)
@@ -8,16 +8,18 @@ Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
  drivers/infiniband/hw/mlx5/mlx5_ib.h               |   2 +
  drivers/infiniband/hw/mlx5/mr.c                    |  12 +
  drivers/net/ethernet/mellanox/mlx5/core/en.h       |  31 ++
- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c   | 235 +++++++++-
+ .../net/ethernet/mellanox/mlx5/core/en_ethtool.c   | 235 ++++++++-
  drivers/net/ethernet/mellanox/mlx5/core/en_fs.c    |   2 +
- drivers/net/ethernet/mellanox/mlx5/core/en_main.c  | 519 ++++++++++++++++++++-
- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c   | 128 ++++-
- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c    |  92 ++++
+ drivers/net/ethernet/mellanox/mlx5/core/en_main.c  | 533 ++++++++++++++++++++-
+ drivers/net/ethernet/mellanox/mlx5/core/en_rep.c   | 150 +++++-
+ drivers/net/ethernet/mellanox/mlx5/core/en_rx.c    | 108 +++++
  .../net/ethernet/mellanox/mlx5/core/en_selftest.c  |   8 +-
- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    | 205 ++++++++
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    | 287 +++++++++++
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.h    |   2 +
  drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c  |  32 ++
  drivers/net/ethernet/mellanox/mlx5/core/eq.c       |  17 +
  drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |   6 +
+ drivers/net/ethernet/mellanox/mlx5/core/eswitch.h  |   2 +
  drivers/net/ethernet/mellanox/mlx5/core/fs_core.c  |   2 +-
  drivers/net/ethernet/mellanox/mlx5/core/health.c   |  18 +
  drivers/net/ethernet/mellanox/mlx5/core/lag.c      |  47 ++
@@ -26,7 +28,7 @@ Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
  drivers/net/ethernet/mellanox/mlx5/core/main.c     |  67 +++
  .../net/ethernet/mellanox/mlx5/core/mlx5_core.h    |   3 +
  include/linux/mlx5/driver.h                        |   3 +
- 23 files changed, 1462 insertions(+), 13 deletions(-)
+ 25 files changed, 1600 insertions(+), 13 deletions(-)
 
 diff --git a/drivers/infiniband/hw/mlx5/ib_virt.c b/drivers/infiniband/hw/mlx5/ib_virt.c
 index xxxxxxx..xxxxxxx xxxxxx
@@ -1172,7 +1174,22 @@ index xxxxxxx..xxxxxxx xxxxxx
        mlx5e_build_icosq_param(priv, icosq_log_wq_sz, &cparam->icosq);
        mlx5e_build_rx_cq_param(priv, params, &cparam->rx_cq);
        mlx5e_build_tx_cq_param(priv, params, &cparam->tx_cq);
-@@ -2765,8 +2840,10 @@ static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
+@@ -2709,8 +2784,14 @@ int mlx5e_open(struct net_device *netdev)
+               mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_UP);
+       mutex_unlock(&priv->state_lock);
++#ifdef HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON
+       if (mlx5e_vxlan_allowed(priv->mdev))
++#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_NDO_UDP_TUNNEL_ADD_EXTENDED)
+               udp_tunnel_get_rx_info(netdev);
++#elif defined(HAVE_NDO_ADD_VXLAN_PORT)
++              vxlan_get_rx_port(netdev);
++#endif
++#endif /* HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON */
+       return err;
+ }
+@@ -2765,8 +2846,10 @@ static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
        if (err)
                return err;
  
@@ -1183,7 +1200,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        rq->mdev = mdev;
  
-@@ -3030,6 +3107,7 @@ void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv)
+@@ -3030,6 +3113,7 @@ void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv)
                mlx5e_destroy_tir(priv->mdev, &priv->direct_tir[i]);
  }
  
@@ -1191,7 +1208,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_modify_channels_scatter_fcs(struct mlx5e_channels *chs, bool enable)
  {
        int err = 0;
-@@ -3043,6 +3121,7 @@ static int mlx5e_modify_channels_scatter_fcs(struct mlx5e_channels *chs, bool en
+@@ -3043,6 +3127,7 @@ static int mlx5e_modify_channels_scatter_fcs(struct mlx5e_channels *chs, bool en
  
        return 0;
  }
@@ -1199,7 +1216,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
  {
-@@ -3058,15 +3137,23 @@ static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
+@@ -3058,15 +3143,23 @@ static int mlx5e_modify_channels_vsd(struct mlx5e_channels *chs, bool vsd)
        return 0;
  }
  
@@ -1225,7 +1242,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        if (tc && tc != MLX5E_MAX_NUM_TC)
                return -EINVAL;
-@@ -3091,10 +3178,25 @@ out:
+@@ -3091,10 +3184,25 @@ out:
        return err;
  }
  
@@ -1251,7 +1268,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        switch (cls_flower->command) {
        case TC_CLSFLOWER_REPLACE:
                return mlx5e_configure_flower(priv, cls_flower);
-@@ -3107,6 +3209,7 @@ static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
+@@ -3107,6 +3215,7 @@ static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
        }
  }
  
@@ -1259,7 +1276,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
                            void *cb_priv)
  {
-@@ -3144,14 +3247,25 @@ static int mlx5e_setup_tc_block(struct net_device *dev,
+@@ -3144,14 +3253,25 @@ static int mlx5e_setup_tc_block(struct net_device *dev,
        }
  }
  #endif
@@ -1285,7 +1302,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  #endif
        case TC_SETUP_QDISC_MQPRIO:
                return mlx5e_setup_tc_mqprio(dev, type_data);
-@@ -3159,15 +3273,79 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
+@@ -3159,15 +3279,79 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
                return -EOPNOTSUPP;
        }
  }
@@ -1367,7 +1384,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (mlx5e_is_uplink_rep(priv)) {
                stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
                stats->rx_bytes   = PPORT_802_3_GET(pstats, a_octets_received_ok);
-@@ -3200,6 +3378,10 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+@@ -3200,6 +3384,10 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
         */
        stats->multicast =
                VPORT_COUNTER_GET(vstats, received_eth_multicast.packets);
@@ -1378,7 +1395,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  }
  
  static void mlx5e_set_rx_mode(struct net_device *dev)
-@@ -3236,7 +3418,11 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
+@@ -3236,7 +3424,11 @@ static int mlx5e_set_mac(struct net_device *netdev, void *addr)
  
  typedef int (*mlx5e_feature_handler)(struct net_device *netdev, bool enable);
  
@@ -1390,7 +1407,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
-@@ -3245,7 +3431,9 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
+@@ -3245,7 +3437,9 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
        int err = 0;
        bool reset;
  
@@ -1400,7 +1417,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        old_params = &priv->channels.params;
        reset = test_bit(MLX5E_STATE_OPENED, &priv->state);
-@@ -3271,10 +3459,13 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
+@@ -3271,10 +3465,13 @@ static int set_feature_lro(struct net_device *netdev, bool enable)
  
        mlx5e_switch_priv_channels(priv, &new_channels, mlx5e_modify_tirs_lro);
  out:
@@ -1414,7 +1431,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3286,7 +3477,9 @@ static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
+@@ -3286,7 +3483,9 @@ static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
  
        return 0;
  }
@@ -1424,7 +1441,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3299,7 +3492,9 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
+@@ -3299,7 +3498,9 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
  
        return 0;
  }
@@ -1434,7 +1451,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int set_feature_rx_all(struct net_device *netdev, bool enable)
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3307,7 +3502,9 @@ static int set_feature_rx_all(struct net_device *netdev, bool enable)
+@@ -3307,7 +3508,9 @@ static int set_feature_rx_all(struct net_device *netdev, bool enable)
  
        return mlx5_set_port_fcs(mdev, !enable);
  }
@@ -1444,7 +1461,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3324,7 +3521,9 @@ static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
+@@ -3324,7 +3527,9 @@ static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
  
        return err;
  }
@@ -1454,7 +1471,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3345,6 +3544,7 @@ unlock:
+@@ -3345,6 +3550,7 @@ unlock:
  
        return err;
  }
@@ -1462,7 +1479,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  #ifdef CONFIG_RFS_ACCEL
  static int set_feature_arfs(struct net_device *netdev, bool enable)
-@@ -3361,13 +3561,23 @@ static int set_feature_arfs(struct net_device *netdev, bool enable)
+@@ -3361,13 +3567,23 @@ static int set_feature_arfs(struct net_device *netdev, bool enable)
  }
  #endif
  
@@ -1486,7 +1503,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        bool enable = !!(wanted_features & feature);
        int err;
  
-@@ -3376,17 +3586,28 @@ static int mlx5e_handle_feature(struct net_device *netdev,
+@@ -3376,17 +3592,28 @@ static int mlx5e_handle_feature(struct net_device *netdev,
  
        err = feature_handler(netdev, enable);
        if (err) {
@@ -1515,7 +1532,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  {
        netdev_features_t oper_features = netdev->features;
        int err = 0;
-@@ -3412,7 +3633,9 @@ static int mlx5e_set_features(struct net_device *netdev,
+@@ -3412,7 +3639,9 @@ static int mlx5e_set_features(struct net_device *netdev,
  
        return 0;
  }
@@ -1525,7 +1542,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
                                            netdev_features_t features)
  {
-@@ -3431,6 +3654,7 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
+@@ -3431,6 +3660,7 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
  
        return features;
  }
@@ -1533,7 +1550,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
  {
-@@ -3476,8 +3700,14 @@ out:
+@@ -3476,8 +3706,14 @@ out:
        return err;
  }
  
@@ -1548,7 +1565,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        struct hwtstamp_config config;
        int err;
  
-@@ -3540,6 +3770,7 @@ int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr)
+@@ -3540,6 +3776,7 @@ int mlx5e_hwstamp_set(struct mlx5e_priv *priv, struct ifreq *ifr)
                            sizeof(config)) ? -EFAULT : 0;
  }
  
@@ -1556,7 +1573,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr)
  {
        struct hwtstamp_config *cfg = &priv->tstamp;
-@@ -3549,6 +3780,7 @@ int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr)
+@@ -3549,6 +3786,7 @@ int mlx5e_hwstamp_get(struct mlx5e_priv *priv, struct ifreq *ifr)
  
        return copy_to_user(ifr->ifr_data, cfg, sizeof(*cfg)) ? -EFAULT : 0;
  }
@@ -1564,7 +1581,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  {
-@@ -3556,14 +3788,19 @@ static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+@@ -3556,14 +3794,19 @@ static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  
        switch (cmd) {
        case SIOCSHWTSTAMP:
@@ -1584,7 +1601,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  #ifdef CONFIG_MLX5_ESWITCH
  static int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
  {
-@@ -3572,20 +3809,31 @@ static int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
+@@ -3572,20 +3815,31 @@ static int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
  
        return mlx5_eswitch_set_vport_mac(mdev->priv.eswitch, vf + 1, mac);
  }
@@ -1616,7 +1633,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
  {
        struct mlx5e_priv *priv = netdev_priv(dev);
-@@ -3593,7 +3841,9 @@ static int mlx5e_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
+@@ -3593,7 +3847,9 @@ static int mlx5e_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
  
        return mlx5_eswitch_set_vport_spoofchk(mdev->priv.eswitch, vf + 1, setting);
  }
@@ -1626,7 +1643,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
  {
        struct mlx5e_priv *priv = netdev_priv(dev);
-@@ -3601,17 +3851,40 @@ static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
+@@ -3601,17 +3857,40 @@ static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
  
        return mlx5_eswitch_set_vport_trust(mdev->priv.eswitch, vf + 1, setting);
  }
@@ -1667,7 +1684,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5_vport_link2ifla(u8 esw_link)
  {
        switch (esw_link) {
-@@ -3633,7 +3906,9 @@ static int mlx5_ifla_link2vport(u8 ifla_link)
+@@ -3633,7 +3912,9 @@ static int mlx5_ifla_link2vport(u8 ifla_link)
        }
        return MLX5_ESW_VPORT_ADMIN_STATE_AUTO;
  }
@@ -1677,7 +1694,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_set_vf_link_state(struct net_device *dev, int vf,
                                   int link_state)
  {
-@@ -3643,7 +3918,9 @@ static int mlx5e_set_vf_link_state(struct net_device *dev, int vf,
+@@ -3643,7 +3924,9 @@ static int mlx5e_set_vf_link_state(struct net_device *dev, int vf,
        return mlx5_eswitch_set_vport_state(mdev->priv.eswitch, vf + 1,
                                            mlx5_ifla_link2vport(link_state));
  }
@@ -1687,7 +1704,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_get_vf_config(struct net_device *dev,
                               int vf, struct ifla_vf_info *ivi)
  {
-@@ -3654,10 +3931,14 @@ static int mlx5e_get_vf_config(struct net_device *dev,
+@@ -3654,10 +3937,14 @@ static int mlx5e_get_vf_config(struct net_device *dev,
        err = mlx5_eswitch_get_vport_config(mdev->priv.eswitch, vf + 1, ivi);
        if (err)
                return err;
@@ -1702,7 +1719,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_get_vf_stats(struct net_device *dev,
                              int vf, struct ifla_vf_stats *vf_stats)
  {
-@@ -3669,6 +3950,8 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
+@@ -3669,6 +3956,8 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
  }
  #endif
  
@@ -1711,7 +1728,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static void mlx5e_add_vxlan_port(struct net_device *netdev,
                                 struct udp_tunnel_info *ti)
  {
-@@ -3696,15 +3979,44 @@ static void mlx5e_del_vxlan_port(struct net_device *netdev,
+@@ -3696,15 +3985,44 @@ static void mlx5e_del_vxlan_port(struct net_device *netdev,
  
        mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 0);
  }
@@ -1726,7 +1743,7 @@ index xxxxxxx..xxxxxxx xxxxxx
 +
 +      mlx5e_vxlan_queue_work(priv, sa_family, be16_to_cpu(port), 1);
 +}
++
 +static void mlx5e_del_vxlan_port(struct net_device *netdev,
 +                               sa_family_t sa_family, __be16 port)
 +{
@@ -1739,7 +1756,7 @@ index xxxxxxx..xxxxxxx xxxxxx
 +}
 +#endif
 +#endif /* HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON */
-+
 +#ifdef HAVE_NETDEV_FEATURES_T
  static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
                                                     struct sk_buff *skb,
@@ -1756,7 +1773,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        switch (vlan_get_protocol(skb)) {
        case htons(ETH_P_IP):
-@@ -3720,6 +4032,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
+@@ -3720,6 +4038,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
        switch (proto) {
        case IPPROTO_GRE:
                return features;
@@ -1764,7 +1781,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        case IPPROTO_UDP:
                udph = udp_hdr(skb);
                port = be16_to_cpu(udph->dest);
-@@ -3727,6 +4040,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
+@@ -3727,6 +4046,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
                /* Verify if UDP port is being offloaded by HW */
                if (mlx5e_vxlan_lookup_port(priv, port))
                        return features;
@@ -1772,7 +1789,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        }
  
  out:
-@@ -3740,8 +4054,14 @@ static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
+@@ -3740,8 +4060,14 @@ static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
  
@@ -1787,7 +1804,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  #ifdef CONFIG_MLX5_EN_IPSEC
        if (mlx5e_ipsec_feature_check(skb, netdev, features))
-@@ -3756,6 +4076,31 @@ static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
+@@ -3756,6 +4082,31 @@ static netdev_features_t mlx5e_features_check(struct sk_buff *skb,
        return features;
  }
  
@@ -1819,7 +1836,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static bool mlx5e_tx_timeout_eq_recover(struct net_device *dev,
                                        struct mlx5e_txqsq *sq)
  {
-@@ -3832,6 +4177,7 @@ static void mlx5e_tx_timeout(struct net_device *dev)
+@@ -3832,6 +4183,7 @@ static void mlx5e_tx_timeout(struct net_device *dev)
        queue_work(priv->wq, &priv->tx_timeout_work);
  }
  
@@ -1827,7 +1844,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-@@ -3848,11 +4194,13 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
+@@ -3848,11 +4200,13 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
                goto unlock;
        }
  
@@ -1841,7 +1858,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
        /* no need for full reset when exchanging programs */
-@@ -3901,6 +4249,9 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
+@@ -3901,6 +4255,9 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
  
                set_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state);
                /* napi_schedule in case we have missed anything */
@@ -1851,7 +1868,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                napi_schedule(&c->napi);
  
                if (old_prog)
-@@ -3912,6 +4263,7 @@ unlock:
+@@ -3912,6 +4269,7 @@ unlock:
        return err;
  }
  
@@ -1859,7 +1876,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static u32 mlx5e_xdp_query(struct net_device *dev)
  {
        struct mlx5e_priv *priv = netdev_priv(dev);
-@@ -3926,6 +4278,14 @@ static u32 mlx5e_xdp_query(struct net_device *dev)
+@@ -3926,6 +4284,14 @@ static u32 mlx5e_xdp_query(struct net_device *dev)
  
        return prog_id;
  }
@@ -1874,7 +1891,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
  {
-@@ -3933,13 +4293,18 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+@@ -3933,13 +4299,18 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
        case XDP_SETUP_PROG:
                return mlx5e_xdp_set(dev, xdp->prog);
        case XDP_QUERY_PROG:
@@ -1893,7 +1910,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  #ifdef CONFIG_NET_POLL_CONTROLLER
  /* Fake "interrupt" called by netpoll (eg netconsole) to send skbs without
-@@ -3961,44 +4326,143 @@ static const struct net_device_ops mlx5e_netdev_ops = {
+@@ -3961,43 +4332,142 @@ static const struct net_device_ops mlx5e_netdev_ops = {
        .ndo_open                = mlx5e_open,
        .ndo_stop                = mlx5e_close,
        .ndo_start_xmit          = mlx5e_xmit,
@@ -2017,10 +2034,10 @@ index xxxxxxx..xxxxxxx xxxxxx
        .ndo_get_offload_stats   = mlx5e_get_offload_stats,
 +#elif defined(HAVE_NDO_GET_OFFLOAD_STATS_EXTENDED)
 +      .extended.ndo_get_offload_stats   = mlx5e_get_offload_stats,
- #endif
++#endif
 +#endif /* CONFIG_MLX5_ESWITCH */
- };
++};
++
 +#ifdef HAVE_NET_DEVICE_OPS_EXT
 +static const struct net_device_ops_ext mlx5e_netdev_ops_ext= {
 +      .size             = sizeof(struct net_device_ops_ext),
@@ -2030,14 +2047,13 @@ index xxxxxxx..xxxxxxx xxxxxx
 +#endif
 +#ifdef HAVE_NETDEV_OPS_EXT_NDO_SET_VF_LINK_STATE
 +      .ndo_set_vf_link_state  = mlx5e_set_vf_link_state,
-+#endif
-+};
+ #endif
+ };
 +#endif /* HAVE_NET_DEVICE_OPS_EXT */
-+
  static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
  {
-       if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
-@@ -4033,13 +4497,49 @@ void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
+@@ -4033,13 +4503,49 @@ void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
                indirection_rqt[i] = i % num_channels;
  }
  
@@ -2087,7 +2103,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        mlx5_core_dbg_once(mdev, "Max link speed = %d, PCI BW = %d\n",
                           link_speed, pci_bw);
  
-@@ -4238,7 +4738,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+@@ -4238,7 +4744,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
        netdev->vlan_features    |= NETIF_F_TSO;
        netdev->vlan_features    |= NETIF_F_TSO6;
        netdev->vlan_features    |= NETIF_F_RXCSUM;
@@ -2097,7 +2113,45 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        netdev->hw_enc_features  |= NETIF_F_HW_VLAN_CTAG_TX;
        netdev->hw_enc_features  |= NETIF_F_HW_VLAN_CTAG_RX;
-@@ -4447,7 +4949,9 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
+@@ -4253,12 +4761,16 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+       netdev->hw_features      |= NETIF_F_HW_VLAN_STAG_TX;
+       if (mlx5e_vxlan_allowed(mdev) || MLX5_CAP_ETH(mdev, tunnel_stateless_gre)) {
++#ifdef HAVE_NETIF_F_GSO_PARTIAL
+               netdev->hw_features     |= NETIF_F_GSO_PARTIAL;
++#endif
+               netdev->hw_enc_features |= NETIF_F_IP_CSUM;
+               netdev->hw_enc_features |= NETIF_F_IPV6_CSUM;
+               netdev->hw_enc_features |= NETIF_F_TSO;
+               netdev->hw_enc_features |= NETIF_F_TSO6;
++#ifdef HAVE_NETIF_F_GSO_PARTIAL
+               netdev->hw_enc_features |= NETIF_F_GSO_PARTIAL;
++#endif
+       }
+       if (mlx5e_vxlan_allowed(mdev)) {
+@@ -4266,7 +4778,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+                                          NETIF_F_GSO_UDP_TUNNEL_CSUM;
+               netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL |
+                                          NETIF_F_GSO_UDP_TUNNEL_CSUM;
++#ifdef HAVE_NETIF_F_GSO_PARTIAL
+               netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
++#endif
+       }
+       if (MLX5_CAP_ETH(mdev, tunnel_stateless_gre)) {
+@@ -4274,8 +4788,10 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
+                                          NETIF_F_GSO_GRE_CSUM;
+               netdev->hw_enc_features |= NETIF_F_GSO_GRE |
+                                          NETIF_F_GSO_GRE_CSUM;
++#ifdef HAVE_NETIF_F_GSO_PARTIAL
+               netdev->gso_partial_features |= NETIF_F_GSO_GRE |
+                                               NETIF_F_GSO_GRE_CSUM;
++#endif
+       }
+       mlx5_query_port_fcs(mdev, &fcs_supported, &fcs_enabled);
+@@ -4447,7 +4963,9 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
  {
        struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
@@ -2107,7 +2161,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        mlx5e_init_l2_addr(priv);
  
-@@ -4455,10 +4959,17 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
+@@ -4455,10 +4973,17 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
        if (!netif_running(netdev))
                mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN);
  
@@ -2129,7 +2183,122 @@ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethe
 index xxxxxxx..xxxxxxx xxxxxx
 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
 +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
-@@ -706,6 +706,7 @@ static int mlx5e_rep_close(struct net_device *dev)
+@@ -290,6 +290,7 @@ void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
+       mlx5e_sqs2vport_stop(esw, rep);
+ }
++#ifdef HAVE_TCF_TUNNEL_INFO
+ static void mlx5e_rep_neigh_update_init_interval(struct mlx5e_rep_priv *rpriv)
+ {
+ #if IS_ENABLED(CONFIG_IPV6)
+@@ -421,9 +422,13 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+       struct mlx5e_neigh_hash_entry *nhe = NULL;
+       struct mlx5e_neigh m_neigh = {};
++#ifdef NETEVENT_DELAY_PROBE_TIME_UPDATE
+       struct neigh_parms *p;
++#endif
+       struct neighbour *n;
++#ifdef NETEVENT_DELAY_PROBE_TIME_UPDATE
+       bool found = false;
++#endif
+       switch (event) {
+       case NETEVENT_NEIGH_UPDATE:
+@@ -436,7 +441,9 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+                       return NOTIFY_DONE;
+               m_neigh.dev = n->dev;
++#ifdef HAVE_TCF_TUNNEL_INFO
+               m_neigh.family = n->ops->family;
++#endif
+               memcpy(&m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
+               /* We are in atomic context and can't take RTNL mutex, so use
+@@ -469,6 +476,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+               spin_unlock_bh(&neigh_update->encap_lock);
+               break;
++#ifdef NETEVENT_DELAY_PROBE_TIME_UPDATE
+       case NETEVENT_DELAY_PROBE_TIME_UPDATE:
+               p = ptr;
+@@ -505,9 +513,11 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+               mlx5_fc_update_sampling_interval(priv->mdev,
+                                                neigh_update->min_interval);
+               break;
++#endif
+       }
+       return NOTIFY_DONE;
+ }
++#endif /* HAVE_TCF_TUNNEL_INFO */
+ static const struct rhashtable_params mlx5e_neigh_ht_params = {
+       .head_offset = offsetof(struct mlx5e_neigh_hash_entry, rhash_node),
+@@ -526,6 +536,7 @@ static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv)
+               return err;
+       INIT_LIST_HEAD(&neigh_update->neigh_list);
++#ifdef HAVE_TCF_TUNNEL_INFO
+       spin_lock_init(&neigh_update->encap_lock);
+       INIT_DELAYED_WORK(&neigh_update->neigh_stats_work,
+                         mlx5e_rep_neigh_stats_work);
+@@ -539,12 +550,14 @@ static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv)
+ out_err:
+       rhashtable_destroy(&neigh_update->neigh_ht);
++#endif
+       return err;
+ }
+ static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv)
+ {
+       struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
++#ifdef HAVE_TCF_TUNNEL_INFO
+       struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
+       unregister_netevent_notifier(&neigh_update->netevent_nb);
+@@ -552,10 +565,12 @@ static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv)
+       flush_workqueue(priv->wq); /* flush neigh update works */
+       cancel_delayed_work_sync(&rpriv->neigh_update.neigh_stats_work);
++#endif
+       rhashtable_destroy(&neigh_update->neigh_ht);
+ }
++#ifdef HAVE_TCF_TUNNEL_INFO
+ static int mlx5e_rep_neigh_entry_insert(struct mlx5e_priv *priv,
+                                       struct mlx5e_neigh_hash_entry *nhe)
+ {
+@@ -578,14 +593,18 @@ static void mlx5e_rep_neigh_entry_remove(struct mlx5e_priv *priv,
+ {
+       struct mlx5e_rep_priv *rpriv = priv->ppriv;
++#ifdef HAVE_TCF_TUNNEL_INFO
+       spin_lock_bh(&rpriv->neigh_update.encap_lock);
++#endif
+       list_del(&nhe->neigh_list);
+       rhashtable_remove_fast(&rpriv->neigh_update.neigh_ht,
+                              &nhe->rhash_node,
+                              mlx5e_neigh_ht_params);
++#ifdef HAVE_TCF_TUNNEL_INFO
+       spin_unlock_bh(&rpriv->neigh_update.encap_lock);
++#endif
+ }
+ /* This function must only be called under RTNL lock or under the
+@@ -667,6 +686,7 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
+       if (list_empty(&nhe->encap_list))
+               mlx5e_rep_neigh_entry_destroy(priv, nhe);
+ }
++#endif /* HAVE_TCF_TUNNEL_INFO */
+ static int mlx5e_rep_open(struct net_device *dev)
+ {
+@@ -706,6 +726,7 @@ static int mlx5e_rep_close(struct net_device *dev)
        return ret;
  }
  
@@ -2137,7 +2306,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
                                        char *buf, size_t len)
  {
-@@ -720,11 +721,35 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
+@@ -720,11 +741,35 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
  
        return 0;
  }
@@ -2173,7 +2342,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        switch (cls_flower->command) {
        case TC_CLSFLOWER_REPLACE:
                return mlx5e_configure_flower(priv, cls_flower);
-@@ -736,7 +761,9 @@ mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
+@@ -736,7 +781,9 @@ mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
                return -EOPNOTSUPP;
        }
  }
@@ -2183,7 +2352,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
                                 void *cb_priv)
  {
-@@ -772,17 +799,47 @@ static int mlx5e_rep_setup_tc_block(struct net_device *dev,
+@@ -772,17 +819,47 @@ static int mlx5e_rep_setup_tc_block(struct net_device *dev,
                return -EOPNOTSUPP;
        }
  }
@@ -2231,7 +2400,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
  {
-@@ -801,6 +858,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
+@@ -801,6 +878,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
        return false;
  }
  
@@ -2239,17 +2408,21 @@ index xxxxxxx..xxxxxxx xxxxxx
  static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
  {
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
-@@ -824,6 +882,7 @@ bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
+@@ -824,7 +902,9 @@ bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
  
        return false;
  }
 +#endif
  
++#if defined(HAVE_NDO_GET_OFFLOAD_STATS) || defined(HAVE_NDO_GET_OFFLOAD_STATS_EXTENDED)
  static int
  mlx5e_get_sw_stats64(const struct net_device *dev,
-@@ -853,12 +912,25 @@ int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
+                    struct rtnl_link_stats64 *stats)
+@@ -852,13 +932,27 @@ int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
        return -EINVAL;
  }
++#endif
  
 -static void
 -mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
@@ -2275,7 +2448,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  }
  
  static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
-@@ -869,11 +941,36 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = {
+@@ -869,11 +963,36 @@ static const struct net_device_ops mlx5e_netdev_ops_rep = {
        .ndo_open                = mlx5e_rep_open,
        .ndo_stop                = mlx5e_rep_close,
        .ndo_start_xmit          = mlx5e_xmit,
@@ -2312,7 +2485,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  };
  
  static void mlx5e_build_rep_params(struct mlx5_core_dev *mdev,
-@@ -906,7 +1003,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
+@@ -906,7 +1025,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
  
        netdev->ethtool_ops       = &mlx5e_rep_ethtool_ops;
  
@@ -2322,7 +2495,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        netdev->features         |= NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
        netdev->hw_features      |= NETIF_F_HW_TC;
-@@ -1071,7 +1170,9 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
+@@ -1071,7 +1192,9 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
        struct mlx5e_rep_priv *uplink_rpriv;
        struct mlx5e_rep_priv *rpriv;
        struct net_device *netdev;
@@ -2332,7 +2505,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        int err;
  
        rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
-@@ -1106,11 +1207,18 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
+@@ -1106,11 +1229,18 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
        }
  
        uplink_rpriv = mlx5_eswitch_get_uplink_priv(dev->priv.eswitch, REP_ETH);
@@ -2351,7 +2524,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        err = register_netdev(netdev);
        if (err) {
-@@ -1122,10 +1230,17 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
+@@ -1122,10 +1252,17 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
        return 0;
  
  err_egdev_cleanup:
@@ -2369,7 +2542,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        mlx5e_rep_neigh_cleanup(rpriv);
  
  err_detach_netdev:
-@@ -1145,14 +1260,23 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
+@@ -1145,14 +1282,23 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5e_rep_priv *uplink_rpriv;
        void *ppriv = priv->ppriv;
@@ -2397,7 +2570,31 @@ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ether
 index xxxxxxx..xxxxxxx xxxxxx
 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
 +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
-@@ -758,6 +758,7 @@ static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq,
+@@ -200,7 +200,11 @@ static inline bool mlx5e_rx_cache_get(struct mlx5e_rq *rq,
+               return false;
+       }
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
+       if (page_ref_count(cache->page_cache[cache->head].page) != 1) {
++#else
++      if (atomic_read(&cache->page_cache[cache->head].page->_count) != 1) {
++#endif
+               rq->stats.cache_busy++;
+               return false;
+       }
+@@ -306,7 +310,11 @@ static inline void mlx5e_add_skb_frag_mpwqe(struct mlx5e_rq *rq,
+       dma_sync_single_for_cpu(rq->pdev,
+                               di->addr + frag_offset,
+                               len, DMA_FROM_DEVICE);
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
+       page_ref_inc(di->page);
++#else
++      atomic_inc(&di->page->_count);
++#endif
+       skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+                       di->page, frag_offset, len, truesize);
+ }
+@@ -758,6 +766,7 @@ static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq,
        mlx5e_build_rx_skb(cqe, cqe_bcnt, rq, skb);
  }
  
@@ -2405,7 +2602,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
  {
        struct mlx5_wq_cyc *wq = &sq->wq;
-@@ -771,7 +772,12 @@ static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
+@@ -771,7 +780,12 @@ static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
  
  static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
                                        struct mlx5e_dma_info *di,
@@ -2418,7 +2615,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  {
        struct mlx5e_xdpsq       *sq   = &rq->xdpsq;
        struct mlx5_wq_cyc       *wq   = &sq->wq;
-@@ -782,8 +788,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
+@@ -782,8 +796,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
        struct mlx5_wqe_eth_seg  *eseg = &wqe->eth;
        struct mlx5_wqe_data_seg *dseg;
  
@@ -2430,7 +2627,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        unsigned int dma_len = xdp->data_end - xdp->data;
  
        prefetchw(wqe);
-@@ -792,6 +801,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
+@@ -792,6 +809,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
                rq->stats.xdp_drop++;
                return false;
        }
@@ -2442,7 +2639,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        if (unlikely(!mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1))) {
                if (sq->db.doorbell) {
-@@ -811,7 +825,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
+@@ -811,7 +833,11 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
  
        /* copy the inline part if required */
        if (sq->min_inline_mode != MLX5_INLINE_MODE_NONE) {
@@ -2454,7 +2651,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                eseg->inline_hdr.sz = cpu_to_be16(MLX5E_XDP_MIN_INLINE);
                dma_len  -= MLX5E_XDP_MIN_INLINE;
                dma_addr += MLX5E_XDP_MIN_INLINE;
-@@ -838,43 +856,75 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
+@@ -838,43 +864,75 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
  }
  
  /* returns true if packet was consumed by xdp */
@@ -2530,7 +2727,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static inline
  struct sk_buff *mlx5e_build_linear_skb(struct mlx5e_rq *rq, void *va,
                                       u32 frag_size, u16 headroom,
-@@ -892,6 +942,7 @@ struct sk_buff *mlx5e_build_linear_skb(struct mlx5e_rq *rq, void *va,
+@@ -892,6 +950,7 @@ struct sk_buff *mlx5e_build_linear_skb(struct mlx5e_rq *rq, void *va,
  
        return skb;
  }
@@ -2538,7 +2735,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static inline
  struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
-@@ -901,7 +952,9 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
+@@ -901,7 +960,9 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
        u16 rx_headroom = rq->buff.headroom;
        struct sk_buff *skb;
        void *va, *data;
@@ -2548,7 +2745,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        u32 frag_size;
  
        va             = page_address(di->page) + wi->offset;
-@@ -918,19 +971,34 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
+@@ -918,19 +979,38 @@ struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
                return NULL;
        }
  
@@ -2574,7 +2771,11 @@ index xxxxxxx..xxxxxxx xxxxxx
                return NULL;
  
        /* queue up for recycling/reuse */
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
        page_ref_inc(di->page);
++#else
++      atomic_inc(&di->page->_count);
++#endif
  
 +#ifdef HAVE_BUILD_SKB
 +      skb_reserve(skb, rx_headroom);
@@ -2583,7 +2784,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        return skb;
  }
  
-@@ -1072,7 +1140,9 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
+@@ -1072,7 +1152,9 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
        struct sk_buff *skb;
        void *va, *data;
        u32 frag_size;
@@ -2593,7 +2794,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        va             = page_address(di->page) + head_offset;
        data           = va + rx_headroom;
-@@ -1082,22 +1152,38 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
+@@ -1082,21 +1164,41 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
                                      frag_size, DMA_FROM_DEVICE);
        prefetch(data);
  
@@ -2622,17 +2823,20 @@ index xxxxxxx..xxxxxxx xxxxxx
                return NULL;
  
        /* queue up for recycling/reuse */
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
        page_ref_inc(di->page);
++#else
++      atomic_inc(&di->page->_count);
++#endif
++
 +#ifdef HAVE_BUILD_SKB
 +      skb_reserve(skb, rx_headroom);
 +      skb_put(skb, cqe_bcnt);
 +#endif
-+
        return skb;
  }
-@@ -1148,7 +1234,9 @@ mpwrq_cqe_out:
+@@ -1148,7 +1250,9 @@ mpwrq_cqe_out:
  int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
  {
        struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq);
@@ -2642,7 +2846,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        struct mlx5_cqe64 *cqe;
        int work_done = 0;
  
-@@ -1162,7 +1250,9 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
+@@ -1162,7 +1266,9 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
        if (!cqe)
                return 0;
  
@@ -2652,7 +2856,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        do {
                if (mlx5_get_cqe_format(cqe) == MLX5_COMPRESSED) {
-@@ -1177,10 +1267,12 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
+@@ -1177,10 +1283,12 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
                rq->handle_rx_cqe(rq, cqe);
        } while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(&cq->wq)));
  
@@ -2720,17 +2924,38 @@ index xxxxxxx..xxxxxxx xxxxxx
  #include <net/arp.h>
  #include "en.h"
  #include "en_rep.h"
-@@ -56,7 +65,9 @@
+@@ -53,11 +62,19 @@
+ #include "vxlan.h"
+ #include "fs_core.h"
++#ifdef HAVE_TCF_TUNNEL_INFO
++#define MLNX_HAIRPIN_SUPPORT
++#endif
++
  struct mlx5_nic_flow_attr {
        u32 action;
        u32 flow_tag;
 +#ifdef HAVE_TCF_PEDIT_TCFP_KEYS_EX
        u32 mod_hdr_id;
 +#endif
++#ifdef MLNX_HAIRPIN_SUPPORT
        u32 hairpin_tirn;
++#endif
        struct mlx5_flow_table  *hairpin_ft;
  };
-@@ -74,8 +85,12 @@ struct mlx5e_tc_flow {
+@@ -65,8 +82,10 @@ enum {
+       MLX5E_TC_FLOW_ESWITCH   = BIT(0),
+       MLX5E_TC_FLOW_NIC       = BIT(1),
+       MLX5E_TC_FLOW_OFFLOADED = BIT(2),
++#ifdef MLNX_HAIRPIN_SUPPORT
+       MLX5E_TC_FLOW_HAIRPIN   = BIT(3),
+       MLX5E_TC_FLOW_HAIRPIN_RSS = BIT(4),
++#endif
+ };
+ struct mlx5e_tc_flow {
+@@ -74,9 +93,15 @@ struct mlx5e_tc_flow {
        u64                     cookie;
        u8                      flags;
        struct mlx5_flow_handle *rule;
@@ -2740,10 +2965,13 @@ index xxxxxxx..xxxxxxx xxxxxx
 +#ifdef HAVE_TCF_PEDIT_TCFP_KEYS_EX
        struct list_head        mod_hdr; /* flows sharing the same mod hdr ID */
 +#endif
++#ifdef MLNX_HAIRPIN_SUPPORT
        struct list_head        hairpin; /* flows sharing the same hairpin */
++#endif
        union {
                struct mlx5_esw_flow_attr esw_attr[0];
-@@ -84,17 +99,25 @@ struct mlx5e_tc_flow {
+               struct mlx5_nic_flow_attr nic_attr[0];
+@@ -84,21 +109,30 @@ struct mlx5e_tc_flow {
  };
  
  struct mlx5e_tc_flow_parse_attr {
@@ -2769,23 +2997,77 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  #define MLX5E_TC_TABLE_NUM_GROUPS 4
  #define MLX5E_TC_TABLE_MAX_GROUP_SIZE (1 << 16)
-@@ -125,6 +148,7 @@ struct mlx5e_hairpin_entry {
++#ifdef MLNX_HAIRPIN_SUPPORT
+ struct mlx5e_hairpin {
+       struct mlx5_hairpin *pair;
+@@ -124,7 +158,9 @@ struct mlx5e_hairpin_entry {
+       u8 prio;
        struct mlx5e_hairpin *hp;
  };
++#endif
  
 +#ifdef HAVE_TCF_PEDIT_TCFP_KEYS_EX
  struct mod_hdr_key {
        int num_actions;
        void *actions;
-@@ -253,6 +277,7 @@ static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
+@@ -253,7 +289,9 @@ static void mlx5e_detach_mod_hdr(struct mlx5e_priv *priv,
                kfree(mh);
        }
  }
 +#endif /* HAVE_TCF_PEDIT_TCFP_KEYS_EX */
  
++#ifdef MLNX_HAIRPIN_SUPPORT
  static
  struct mlx5_core_dev *mlx5e_hairpin_get_mdev(struct net *net, int ifindex)
-@@ -715,6 +740,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+ {
+@@ -664,8 +702,13 @@ static void mlx5e_hairpin_flow_del(struct mlx5e_priv *priv,
+               kfree(hpe);
+       }
+ }
++#endif /* MLNX_HAIRPIN_SUPPORT */
++#ifdef HAVE_TCF_TUNNEL_INFO
+ static struct mlx5_flow_handle *
++#else
++static int
++#endif
+ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+                     struct mlx5e_tc_flow_parse_attr *parse_attr,
+                     struct mlx5e_tc_flow *flow)
+@@ -684,6 +727,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+       bool table_created = false;
+       int err, dest_ix = 0;
++#ifdef MLNX_HAIRPIN_SUPPORT
+       if (flow->flags & MLX5E_TC_FLOW_HAIRPIN) {
+               err = mlx5e_hairpin_flow_add(priv, flow, parse_attr);
+               if (err) {
+@@ -703,18 +747,30 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+               dest[dest_ix].ft = priv->fs.vlan.ft.t;
+               dest_ix++;
+       }
++#else
++      if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
++              dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
++              dest[dest_ix].ft = priv->fs.vlan.ft.t;
++              dest_ix++;
++      }
++#endif
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+               counter = mlx5_fc_create(dev, true);
+               if (IS_ERR(counter)) {
++#ifdef MLNX_HAIRPIN_SUPPORT
+                       rule = ERR_CAST(counter);
+                       goto err_fc_create;
++#else
++                      return PTR_ERR(counter);
++#endif
+               }
+               dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+               dest[dest_ix].counter = counter;
                dest_ix++;
        }
  
@@ -2793,7 +3075,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
                err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
                flow_act.modify_id = attr->mod_hdr_id;
-@@ -724,6 +750,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+@@ -724,6 +780,7 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
                        goto err_create_mod_hdr_id;
                }
        }
@@ -2801,7 +3083,19 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        if (IS_ERR_OR_NULL(priv->fs.tc.t)) {
                int tc_grp_size, tc_tbl_size;
-@@ -768,9 +795,11 @@ err_add_rule:
+@@ -760,7 +817,11 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+       if (IS_ERR(rule))
+               goto err_add_rule;
++#ifdef HAVE_TCF_TUNNEL_INFO
+       return rule;
++#else
++      return 0;
++#endif
+ err_add_rule:
+       if (table_created) {
+@@ -768,21 +829,31 @@ err_add_rule:
                priv->fs.tc.t = NULL;
        }
  err_create_ft:
@@ -2811,9 +3105,19 @@ index xxxxxxx..xxxxxxx xxxxxx
  err_create_mod_hdr_id:
 +#endif
        mlx5_fc_destroy(dev, counter);
++#ifdef MLNX_HAIRPIN_SUPPORT
  err_fc_create:
        if (flow->flags & MLX5E_TC_FLOW_HAIRPIN)
-@@ -782,7 +811,9 @@ err_add_hairpin_flow:
+               mlx5e_hairpin_flow_del(priv, flow);
+ err_add_hairpin_flow:
++#endif
++#ifdef HAVE_TCF_TUNNEL_INFO
+       return rule;
++#else
++      return err;
++#endif
+ }
  static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
                                  struct mlx5e_tc_flow *flow)
  {
@@ -2823,7 +3127,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        struct mlx5_fc *counter = NULL;
  
        counter = mlx5_flow_rule_counter(flow->rule);
-@@ -794,13 +825,16 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
+@@ -794,13 +865,18 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
                priv->fs.tc.t = NULL;
        }
  
@@ -2832,23 +3136,30 @@ index xxxxxxx..xxxxxxx xxxxxx
                mlx5e_detach_mod_hdr(priv, flow);
 +#endif
  
++#ifdef MLNX_HAIRPIN_SUPPORT
        if (flow->flags & MLX5E_TC_FLOW_HAIRPIN)
                mlx5e_hairpin_flow_del(priv, flow);
++#endif
  }
  
 +#ifdef HAVE_TCF_TUNNEL_INFO
  static void mlx5e_detach_encap(struct mlx5e_priv *priv,
                               struct mlx5e_tc_flow *flow);
  
-@@ -809,6 +843,7 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
+@@ -809,27 +885,37 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
                              struct net_device *mirred_dev,
                              struct net_device **encap_dev,
                              struct mlx5e_tc_flow *flow);
 +#endif
  
++#ifdef HAVE_TCF_TUNNEL_INFO
  static struct mlx5_flow_handle *
++#else
++static int
++#endif
  mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
-@@ -817,12 +852,15 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+                     struct mlx5e_tc_flow_parse_attr *parse_attr,
+                     struct mlx5e_tc_flow *flow)
  {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_esw_flow_attr *attr = flow->esw_attr;
@@ -2864,7 +3175,16 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
                out_dev = __dev_get_by_index(dev_net(priv->netdev),
                                             attr->parse_attr->mirred_ifindex);
-@@ -837,6 +875,7 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+               err = mlx5e_attach_encap(priv, &parse_attr->tun_info,
+                                        out_dev, &encap_dev, flow);
+               if (err) {
++#ifdef HAVE_TCF_TUNNEL_INFO
+                       rule = ERR_PTR(err);
++#endif
+                       if (err != -EAGAIN)
+                               goto err_attach_encap;
+               }
+@@ -837,22 +923,30 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
                rpriv = out_priv->ppriv;
                attr->out_rep = rpriv->rep;
        }
@@ -2872,7 +3192,9 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        err = mlx5_eswitch_add_vlan_action(esw, attr);
        if (err) {
-@@ -844,6 +883,7 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
++#ifdef HAVE_TCF_TUNNEL_INFO
+               rule = ERR_PTR(err);
++#endif
                goto err_add_vlan;
        }
  
@@ -2880,7 +3202,10 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
                err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
                kfree(parse_attr->mod_hdr_actions);
-@@ -852,7 +892,9 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+               if (err) {
++#ifdef HAVE_TCF_TUNNEL_INFO
+                       rule = ERR_PTR(err);
++#endif
                        goto err_mod_hdr;
                }
        }
@@ -2890,7 +3215,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        /* we get here if (1) there's no error (rule being null) or when
         * (2) there's an encap action and we're on -EAGAIN (no valid neigh)
         */
-@@ -864,14 +906,19 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+@@ -864,15 +958,22 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
        return rule;
  
  err_add_rule:
@@ -2906,11 +3231,14 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
                mlx5e_detach_encap(priv, flow);
  err_attach_encap:
-+#endif
        return rule;
++#else
++      return err;
++#endif
  }
  
-@@ -882,21 +929,28 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
+ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
+@@ -882,21 +983,28 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
        struct mlx5_esw_flow_attr *attr = flow->esw_attr;
  
        if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
@@ -2939,7 +3267,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
                              struct mlx5e_encap_entry *e)
  {
-@@ -1021,6 +1075,7 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
+@@ -1021,6 +1129,7 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
                kfree(e);
        }
  }
@@ -2947,7 +3275,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow)
-@@ -1031,6 +1086,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
+@@ -1031,6 +1140,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
                mlx5e_tc_del_nic_flow(priv, flow);
  }
  
@@ -2955,7 +3283,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static void parse_vxlan_attr(struct mlx5_flow_spec *spec,
                             struct tc_cls_flower_offload *f)
  {
-@@ -1186,6 +1242,7 @@ vxlan_match_offload_err:
+@@ -1186,6 +1296,7 @@ vxlan_match_offload_err:
  
        return 0;
  }
@@ -2963,7 +3291,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static int __parse_cls_flower(struct mlx5e_priv *priv,
                              struct mlx5_flow_spec *spec,
-@@ -1205,22 +1262,37 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1205,22 +1316,37 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
            ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
              BIT(FLOW_DISSECTOR_KEY_BASIC) |
              BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
@@ -3001,7 +3329,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if ((dissector_uses_key(f->dissector,
                                FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) ||
             dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID) ||
-@@ -1248,6 +1320,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1248,6 +1374,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
                                         inner_headers);
        }
@@ -3009,7 +3337,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
                struct flow_dissector_key_control *key =
-@@ -1326,6 +1399,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1326,6 +1453,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                                key->src);
        }
  
@@ -3017,7 +3345,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
                struct flow_dissector_key_vlan *key =
                        skb_flow_dissector_target(f->dissector,
-@@ -1345,6 +1419,23 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1345,6 +1473,23 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                        MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, mask->vlan_priority);
                        MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, key->vlan_priority);
                }
@@ -3041,7 +3369,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        }
  
        if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
-@@ -1403,6 +1494,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1403,6 +1548,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                        *min_inline = MLX5_INLINE_MODE_IP;
        }
  
@@ -3049,7 +3377,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) {
                struct flow_dissector_key_ip *key =
                        skb_flow_dissector_target(f->dissector,
-@@ -1430,6 +1522,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1430,6 +1576,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                if (mask->tos || mask->ttl)
                        *min_inline = MLX5_INLINE_MODE_IP;
        }
@@ -3057,7 +3385,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
                struct flow_dissector_key_ports *key =
-@@ -1474,6 +1567,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1474,6 +1621,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                        *min_inline = MLX5_INLINE_MODE_TCP_UDP;
        }
  
@@ -3065,7 +3393,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) {
                struct flow_dissector_key_tcp *key =
                        skb_flow_dissector_target(f->dissector,
-@@ -1492,6 +1586,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1492,6 +1640,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                if (mask->flags)
                        *min_inline = MLX5_INLINE_MODE_TCP_UDP;
        }
@@ -3073,7 +3401,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        return 0;
  }
-@@ -1525,6 +1620,7 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
+@@ -1525,6 +1674,7 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
        return err;
  }
  
@@ -3081,7 +3409,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  struct pedit_headers {
        struct ethhdr  eth;
        struct iphdr   ip4;
-@@ -1810,6 +1906,7 @@ out_err:
+@@ -1810,6 +1960,7 @@ out_err:
        return err;
  }
  
@@ -3089,7 +3417,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 update_flags)
  {
        u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP |
-@@ -1831,6 +1928,7 @@ static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 upda
+@@ -1831,6 +1982,7 @@ static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 upda
  
        return true;
  }
@@ -3097,15 +3425,25 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
                                          struct tcf_exts *exts)
-@@ -1895,6 +1993,7 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
+@@ -1895,7 +2047,9 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
  
        return true;
  }
 +#endif /* HAVE_TCF_PEDIT_TCFP_KEYS_EX */
  
++#ifdef MLNX_HAIRPIN_SUPPORT
  static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv)
  {
-@@ -1917,16 +2016,26 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+       struct mlx5_core_dev *fmdev, *pmdev;
+@@ -1909,6 +2063,7 @@ static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv)
+       return (func_id == peer_id);
+ }
++#endif
+ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+                               struct mlx5e_tc_flow_parse_attr *parse_attr,
+@@ -1917,16 +2072,26 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
        struct mlx5_nic_flow_attr *attr = flow->nic_attr;
        const struct tc_action *a;
        LIST_HEAD(actions);
@@ -3132,7 +3470,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                if (is_tcf_gact_shot(a)) {
                        attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
                        if (MLX5_CAP_FLOWTABLE(priv->mdev,
-@@ -1935,6 +2044,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -1935,6 +2100,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                        continue;
                }
  
@@ -3140,7 +3478,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                if (is_tcf_pedit(a)) {
                        err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_KERNEL,
                                                    parse_attr);
-@@ -1945,7 +2055,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -1945,7 +2111,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                                        MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
                        continue;
                }
@@ -3150,12 +3488,13 @@ index xxxxxxx..xxxxxxx xxxxxx
                if (is_tcf_csum(a)) {
                        if (csum_offload_supported(priv, attr->action,
                                                   tcf_csum_update_flags(a)))
-@@ -1953,9 +2065,16 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -1953,13 +2121,23 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
  
                        return -EOPNOTSUPP;
                }
 +#endif
  
++#ifdef MLNX_HAIRPIN_SUPPORT
                if (is_tcf_mirred_egress_redirect(a)) {
 +#ifndef HAVE_TCF_MIRRED_DEV
 +                      int ifindex = tcf_mirred_ifindex(a);
@@ -3167,7 +3506,21 @@ index xxxxxxx..xxxxxxx xxxxxx
  
                        if (priv->netdev->netdev_ops == peer_dev->netdev_ops &&
                            same_hw_devs(priv, netdev_priv(peer_dev))) {
-@@ -1988,12 +2107,15 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
++#ifdef HAVE_TCF_TUNNEL_INFO
+                               parse_attr->mirred_ifindex = peer_dev->ifindex;
++#endif
+                               flow->flags |= MLX5E_TC_FLOW_HAIRPIN;
+                               attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+                                               MLX5_FLOW_CONTEXT_ACTION_COUNT;
+@@ -1970,6 +2148,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+                       }
+                       continue;
+               }
++#endif
+               if (is_tcf_skbedit_mark(a)) {
+                       u32 mark = tcf_skbedit_mark(a);
+@@ -1988,12 +2167,15 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                return -EINVAL;
        }
  
@@ -3183,7 +3536,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static inline int cmp_encap_info(struct ip_tunnel_key *a,
                                 struct ip_tunnel_key *b)
  {
-@@ -2448,33 +2570,53 @@ out_err:
+@@ -2448,33 +2630,53 @@ out_err:
        kfree(e);
        return err;
  }
@@ -3237,7 +3590,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                if (is_tcf_pedit(a)) {
                        err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB,
                                                    parse_attr);
-@@ -2484,7 +2626,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2484,7 +2686,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                        attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
                        continue;
                }
@@ -3247,7 +3600,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                if (is_tcf_csum(a)) {
                        if (csum_offload_supported(priv, attr->action,
                                                   tcf_csum_update_flags(a)))
-@@ -2492,12 +2636,19 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2492,12 +2696,19 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
  
                        return -EOPNOTSUPP;
                }
@@ -3267,7 +3620,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
                        if (switchdev_port_same_parent_id(priv->netdev,
                                                          out_dev)) {
-@@ -2506,8 +2657,13 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2506,8 +2717,13 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                                out_priv = netdev_priv(out_dev);
                                rpriv = out_priv->ppriv;
                                attr->out_rep = rpriv->rep;
@@ -3281,7 +3634,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                                parse_attr->tun_info = *info;
                                attr->parse_attr = parse_attr;
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
-@@ -2531,6 +2687,20 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2531,6 +2747,19 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                        continue;
                }
  
@@ -3294,7 +3647,6 @@ index xxxxxxx..xxxxxxx xxxxxx
 +                      attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
 +                              MLX5_FLOW_CONTEXT_ACTION_COUNT;
 +                      out_priv = netdev_priv(out_dev);
-+                      attr->out_rep[attr->out_count++] = out_priv->ppriv;
 +                      continue;
 +              }
 +#endif /* HAVE_TCF_TUNNEL_INFO */
@@ -3302,7 +3654,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                if (is_tcf_vlan(a)) {
                        if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
-@@ -2552,16 +2722,20 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
+@@ -2552,16 +2781,20 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                        continue;
                }
  
@@ -3323,7 +3675,53 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        return err;
  }
-@@ -2664,6 +2838,10 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
+@@ -2599,24 +2832,45 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv,
+               goto err_free;
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
++#ifdef HAVE_TCF_TUNNEL_INFO
+               err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow);
++#else
++              err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow->esw_attr);
++#endif
+               if (err < 0)
+                       goto err_free;
++#ifdef HAVE_TCF_TUNNEL_INFO
+               flow->rule = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow);
++#else
++              err = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow);
++#endif
+       } else {
+               err = parse_tc_nic_actions(priv, f->exts, parse_attr, flow);
+               if (err < 0)
+                       goto err_free;
++#ifdef HAVE_TCF_TUNNEL_INFO
+               flow->rule = mlx5e_tc_add_nic_flow(priv, parse_attr, flow);
++#else
++              err = mlx5e_tc_add_nic_flow(priv, parse_attr, flow);
++#endif
+       }
++#ifdef HAVE_TCF_TUNNEL_INFO
+       if (IS_ERR(flow->rule)) {
+               err = PTR_ERR(flow->rule);
+               if (err != -EAGAIN)
+                       goto err_free;
+       }
++#else
++      if (err && err != -EAGAIN)
++              goto err_free;
++#endif
++#ifdef HAVE_TCF_TUNNEL_INFO
+       if (err != -EAGAIN)
++#else
++      if (!err)
++#endif
+               flow->flags |= MLX5E_TC_FLOW_OFFLOADED;
+       if (!(flow->flags & MLX5E_TC_FLOW_ESWITCH) ||
+@@ -2664,6 +2918,10 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
        struct mlx5e_tc_table *tc = &priv->fs.tc;
        struct mlx5e_tc_flow *flow;
        struct mlx5_fc *counter;
@@ -3334,7 +3732,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        u64 bytes;
        u64 packets;
        u64 lastuse;
-@@ -2682,7 +2860,32 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
+@@ -2682,7 +2940,32 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
  
        mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
  
@@ -3367,16 +3765,39 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        return 0;
  }
-@@ -2698,7 +2901,9 @@ int mlx5e_tc_init(struct mlx5e_priv *priv)
+@@ -2698,8 +2981,12 @@ int mlx5e_tc_init(struct mlx5e_priv *priv)
  {
        struct mlx5e_tc_table *tc = &priv->fs.tc;
  
 +#ifdef HAVE_TCF_PEDIT_TCFP_KEYS_EX
        hash_init(tc->mod_hdr_tbl);
 +#endif
++#ifdef MLNX_HAIRPIN_SUPPORT
        hash_init(tc->hairpin_tbl);
++#endif
  
        tc->ht_params = mlx5e_tc_flow_ht_params;
+       return rhashtable_init(&tc->ht, &tc->ht_params);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
+@@ -49,6 +49,7 @@ int mlx5e_delete_flower(struct mlx5e_priv *priv,
+ int mlx5e_stats_flower(struct mlx5e_priv *priv,
+                      struct tc_cls_flower_offload *f);
++#ifdef HAVE_TCF_TUNNEL_INFO
+ struct mlx5e_encap_entry;
+ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
+                             struct mlx5e_encap_entry *e);
+@@ -57,6 +58,7 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv,
+ struct mlx5e_neigh_hash_entry;
+ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe);
++#endif
+ static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv)
+ {
 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
 index xxxxxxx..xxxxxxx xxxxxx
 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
@@ -3545,6 +3966,20 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  free_out:
        kvfree(out);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+@@ -238,7 +238,9 @@ struct mlx5_esw_flow_attr {
+       bool    vlan_handled;
+       u32     encap_id;
+       u32     mod_hdr_id;
++#ifdef HAVE_TCF_TUNNEL_INFO
+       struct mlx5e_tc_flow_parse_attr *parse_attr;
++#endif
+ };
+ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode);
 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
 index xxxxxxx..xxxxxxx xxxxxx
 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 884c9a4ba9eeeb17afc85a6f67b8245acc1a44ee..1db148b1606ee63aab0fdec3e3a066a044fb6a27 100644 (file)
@@ -1,17 +1,17 @@
 From: Vladimir Sokolovsky <vlad@mellanox.com>
-Subject: [PATCH] mlx4
+Subject: [PATCH] BACKPORT: mlx4
 
 Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
 ---
  drivers/net/ethernet/mellanox/mlx4/catas.c       |  17 +
  drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c   |  29 ++
  drivers/net/ethernet/mellanox/mlx4/en_ethtool.c  |   8 +
- drivers/net/ethernet/mellanox/mlx4/en_netdev.c   | 378 ++++++++++++++++++++++-
- drivers/net/ethernet/mellanox/mlx4/en_rx.c       |  66 +++-
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c   | 426 ++++++++++++++++++++++-
+ drivers/net/ethernet/mellanox/mlx4/en_rx.c       |  70 +++-
  drivers/net/ethernet/mellanox/mlx4/en_selftest.c |   4 +-
  drivers/net/ethernet/mellanox/mlx4/main.c        |   2 +
  drivers/net/ethernet/mellanox/mlx4/mlx4_en.h     |  12 +
- 8 files changed, 508 insertions(+), 8 deletions(-)
+ 8 files changed, 560 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c
 index xxxxxxx..xxxxxxx xxxxxx
@@ -709,9 +709,65 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port,
                                  VXLAN_STEER_BY_OUTER_MAC, 0);
-@@ -2741,12 +2904,19 @@ static void mlx4_en_del_vxlan_port(struct  net_device *dev,
+@@ -2689,6 +2852,8 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
+       priv->vxlan_port = 0;
+ }
++#ifdef HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON
++#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_NDO_UDP_TUNNEL_ADD_EXTENDED)
+ static void mlx4_en_add_vxlan_port(struct  net_device *dev,
+                                  struct udp_tunnel_info *ti)
+ {
+@@ -2740,13 +2905,66 @@ static void mlx4_en_del_vxlan_port(struct  net_device *dev,
        queue_work(priv->mdev->workqueue, &priv->vxlan_del_task);
  }
++#elif defined(HAVE_NDO_ADD_VXLAN_PORT)
++static void mlx4_en_add_vxlan_port(struct  net_device *dev,
++                                 sa_family_t sa_family, __be16 port)
++{
++      struct mlx4_en_priv *priv = netdev_priv(dev);
++      __be16 current_port;
++
++      if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
++              return;
++
++      if (sa_family == AF_INET6)
++              return;
++
++      current_port = priv->vxlan_port;
++      if (current_port && current_port != port) {
++              en_warn(priv, "vxlan port %d configured, can't add port %d\n",
++                      ntohs(current_port), ntohs(port));
++              return;
++      }
++
++      priv->vxlan_port = port;
++      queue_work(priv->mdev->workqueue, &priv->vxlan_add_task);
++}
++
++static void mlx4_en_del_vxlan_port(struct  net_device *dev,
++                                 sa_family_t sa_family, __be16 port)
++{
++      struct mlx4_en_priv *priv = netdev_priv(dev);
++      __be16 current_port;
++
++      if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
++              return;
++
++      if (sa_family == AF_INET6)
++              return;
++
++      current_port = priv->vxlan_port;
++      if (current_port != port) {
++              en_dbg(DRV, priv, "vxlan port %d isn't configured, ignoring\n", ntohs(port));
++              return;
++      }
++
++      queue_work(priv->mdev->workqueue, &priv->vxlan_del_task);
++}
++#endif
++#endif /* HAVE_KERNEL_WITH_VXLAN_SUPPORT_ON */
  
 +#ifdef HAVE_NETDEV_FEATURES_T
  static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
@@ -729,7 +785,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        /* The ConnectX-3 doesn't support outer IPv6 checksums but it does
         * support inner IPv6 checksums and segmentation so  we need to
-@@ -2765,6 +2935,7 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
+@@ -2765,6 +2983,7 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
        return features;
  }
  
@@ -737,7 +793,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 maxrate)
  {
        struct mlx4_en_priv *priv = netdev_priv(dev);
-@@ -2791,7 +2962,9 @@ static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 m
+@@ -2791,7 +3010,9 @@ static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 m
                             &params);
        return err;
  }
@@ -747,7 +803,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
  {
        struct mlx4_en_priv *priv = netdev_priv(dev);
-@@ -2855,7 +3028,11 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
+@@ -2855,7 +3076,11 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
                en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n");
        }
  
@@ -759,7 +815,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (err) {
                if (prog)
                        bpf_prog_sub(prog, priv->rx_ring_num - 1);
-@@ -2896,6 +3073,7 @@ out:
+@@ -2896,6 +3121,7 @@ out:
        return err;
  }
  
@@ -767,7 +823,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  static u32 mlx4_xdp_query(struct net_device *dev)
  {
        struct mlx4_en_priv *priv = netdev_priv(dev);
-@@ -2916,6 +3094,14 @@ static u32 mlx4_xdp_query(struct net_device *dev)
+@@ -2916,6 +3142,14 @@ static u32 mlx4_xdp_query(struct net_device *dev)
  
        return prog_id;
  }
@@ -782,7 +838,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
  static int mlx4_xdp(struct net_device *dev, struct netdev_bpf *xdp)
  {
-@@ -2923,24 +3109,40 @@ static int mlx4_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+@@ -2923,24 +3157,40 @@ static int mlx4_xdp(struct net_device *dev, struct netdev_bpf *xdp)
        case XDP_SETUP_PROG:
                return mlx4_xdp_set(dev, xdp->prog);
        case XDP_QUERY_PROG:
@@ -823,7 +879,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        .ndo_do_ioctl           = mlx4_en_ioctl,
        .ndo_tx_timeout         = mlx4_en_tx_timeout,
        .ndo_vlan_rx_add_vid    = mlx4_en_vlan_rx_add_vid,
-@@ -2948,21 +3150,73 @@ static const struct net_device_ops mlx4_netdev_ops = {
+@@ -2948,21 +3198,73 @@ static const struct net_device_ops mlx4_netdev_ops = {
  #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = mlx4_en_netpoll,
  #endif
@@ -897,7 +953,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        .ndo_open               = mlx4_en_open,
        .ndo_stop               = mlx4_en_close,
        .ndo_start_xmit         = mlx4_en_xmit,
-@@ -2971,12 +3225,20 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
+@@ -2971,12 +3273,20 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
        .ndo_set_rx_mode        = mlx4_en_set_rx_mode,
        .ndo_set_mac_address    = mlx4_en_set_mac,
        .ndo_validate_addr      = eth_validate_addr,
@@ -918,7 +974,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        .ndo_set_vf_rate        = mlx4_en_set_vf_rate,
        .ndo_set_vf_spoofchk    = mlx4_en_set_vf_spoofchk,
        .ndo_set_vf_link_state  = mlx4_en_set_vf_link_state,
-@@ -2987,16 +3249,47 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
+@@ -2987,16 +3297,47 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
  #endif
        .ndo_set_features       = mlx4_en_set_features,
        .ndo_fix_features       = mlx4_en_fix_features,
@@ -966,7 +1022,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  };
  
  struct mlx4_en_bond {
-@@ -3424,24 +3717,35 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+@@ -3424,24 +3765,35 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
        netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
  
@@ -1002,7 +1058,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN)) {
                dev->features |= NETIF_F_HW_VLAN_STAG_RX |
                        NETIF_F_HW_VLAN_STAG_FILTER;
-@@ -3475,45 +3779,93 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+@@ -3475,45 +3827,93 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
                      MLX4_DEV_CAP_FLAG2_SKIP_OUTER_VLAN))
                        dev->hw_features |= NETIF_F_HW_VLAN_STAG_TX;
        }
@@ -1096,7 +1152,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        mdev->pndev[port] = dev;
        mdev->upper[port] = NULL;
-@@ -3599,8 +3951,12 @@ int mlx4_en_reset_config(struct net_device *dev,
+@@ -3599,8 +3999,12 @@ int mlx4_en_reset_config(struct net_device *dev,
  
        if (priv->hwtstamp_config.tx_type == ts_config.tx_type &&
            priv->hwtstamp_config.rx_filter == ts_config.rx_filter &&
@@ -1109,7 +1165,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                return 0; /* Nothing to change */
  
        if (DEV_FEATURE_CHANGED(dev, features, NETIF_F_HW_VLAN_CTAG_RX) &&
-@@ -3619,7 +3975,11 @@ int mlx4_en_reset_config(struct net_device *dev,
+@@ -3619,7 +4023,11 @@ int mlx4_en_reset_config(struct net_device *dev,
        memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
        memcpy(&new_prof.hwtstamp_config, &ts_config, sizeof(ts_config));
  
@@ -1121,7 +1177,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        if (err)
                goto out;
  
-@@ -3639,18 +3999,26 @@ int mlx4_en_reset_config(struct net_device *dev,
+@@ -3639,18 +4047,26 @@ int mlx4_en_reset_config(struct net_device *dev,
                /* RX time-stamping is OFF, update the RX vlan offload
                 * to the latest wanted state
                 */
@@ -1217,7 +1273,19 @@ index xxxxxxx..xxxxxxx xxxxxx
        mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
        kvfree(ring->rx_info);
        ring->rx_info = NULL;
-@@ -657,11 +671,17 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -510,7 +524,11 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
+                       dma_unmap_page(priv->ddev, dma, PAGE_SIZE, priv->dma_dir);
+                       frags->page = NULL;
+               } else {
++#ifdef HAVE_PAGE_REF_COUNT_ADD_SUB_INC
+                       page_ref_inc(page);
++#else
++                      atomic_inc(&frags->page->_count);
++#endif
+               }
+               nr++;
+@@ -657,11 +675,17 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
        struct mlx4_en_priv *priv = netdev_priv(dev);
        int factor = priv->cqe_factor;
        struct mlx4_en_rx_ring *ring;
@@ -1235,7 +1303,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        int polled = 0;
        int index;
  
-@@ -670,11 +690,15 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -670,11 +694,15 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
  
        ring = priv->rx_ring[cq_ring];
  
@@ -1251,7 +1319,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
        /* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
         * descriptor offset can be deduced from the CQE index instead of
-@@ -757,9 +781,12 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -757,9 +785,12 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                /* A bpf program gets first chance to drop the packet. It may
                 * read bytes but not past the end of the frag.
                 */
@@ -1264,7 +1332,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                        u32 act;
  
                        dma = frags[0].dma + frags[0].page_offset;
-@@ -767,20 +794,29 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -767,20 +798,29 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                                                priv->frag_info[0].frag_size,
                                                DMA_FROM_DEVICE);
  
@@ -1294,7 +1362,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
                        switch (act) {
                        case XDP_PASS:
-@@ -792,18 +828,23 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+@@ -792,18 +832,23 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                                        frags[0].page = NULL;
                                        goto next;
                                }
@@ -1318,7 +1386,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
                ring->bytes += length;
                ring->packets++;
-@@ -885,13 +926,17 @@ next:
+@@ -885,13 +930,17 @@ next:
                        break;
        }
  
@@ -1336,7 +1404,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
                mlx4_cq_set_ci(&cq->mcq);
                wmb(); /* ensure HW sees CQ consumer before we post new buffers */
-@@ -940,7 +985,9 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
+@@ -940,7 +989,9 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
        /* If we used up all the quota - we're probably not done yet... */
        if (done == budget || !clean_complete) {
                const struct cpumask *aff;
@@ -1346,7 +1414,7 @@ index xxxxxxx..xxxxxxx xxxxxx
                int cpu_curr;
  
                /* in case we got here because of !clean_complete */
-@@ -949,8 +996,12 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
+@@ -949,8 +1000,12 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
                INC_PERF_COUNTER(priv->pstats.napi_quota);
  
                cpu_curr = smp_processor_id();
@@ -1359,7 +1427,7 @@ index xxxxxxx..xxxxxxx xxxxxx
  
                if (likely(cpumask_test_cpu(cpu_curr, aff)))
                        return budget;
-@@ -965,8 +1016,18 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
+@@ -965,8 +1020,18 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
                        done--;
        }
        /* Done for now */
@@ -1378,7 +1446,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        return done;
  }
  
-@@ -976,6 +1037,7 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
+@@ -976,6 +1041,7 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
        int eff_mtu = MLX4_EN_EFF_MTU(dev->mtu);
        int i = 0;
  
@@ -1386,7 +1454,7 @@ index xxxxxxx..xxxxxxx xxxxxx
        /* bpf requires buffers to be set up as 1 packet per page.
         * This only works when num_frags == 1.
         */
-@@ -988,7 +1050,9 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
+@@ -988,7 +1054,9 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
                priv->dma_dir = PCI_DMA_BIDIRECTIONAL;
                priv->rx_headroom = XDP_PACKET_HEADROOM;
                i = 1;