--- /dev/null
+From: Vladimir Sokolovsky <vlad@mellanox.com>
+Subject: [PATCH] BACKPORT: mlx5
+
+Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 26 ++++++++++++++++++++++++
+ drivers/net/ethernet/mellanox/mlx5/core/main.c | 17 +++++++++++++++
+ include/linux/mlx5/driver.h | 5 ++++
+ 3 files changed, 48 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+@@ -512,7 +512,11 @@ static void cmd_work_handler(struct work_struct *work)
+ lay->status_own = CMD_OWNER_HW;
+ set_signature(ent, !cmd->checksum_disabled);
+ dump_command(dev, ent, 1);
++#ifdef HAVE_KTIME_GET_NS
+ ent->ts1 = ktime_get_ns();
++#else
++ ktime_get_ts(&ent->ts1);
++#endif
+
+ /* ring doorbell after the descriptor is valid */
+ wmb();
+@@ -602,6 +606,9 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
+ struct mlx5_cmd *cmd = &dev->cmd;
+ struct mlx5_cmd_work_ent *ent;
+ struct mlx5_cmd_stats *stats;
++#ifndef HAVE_KTIME_GET_NS
++ ktime_t t1, t2, delta;
++#endif
+ int err = 0;
+ s64 ds;
+ u16 op;
+@@ -631,7 +638,14 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
+ if (err == -ETIMEDOUT)
+ goto out;
+
++#ifdef HAVE_KTIME_GET_NS
+ ds = ent->ts2 - ent->ts1;
++#else
++ t1 = timespec_to_ktime(ent->ts1);
++ t2 = timespec_to_ktime(ent->ts2);
++ delta = ktime_sub(t2, t1);
++ ds = ktime_to_ns(delta);
++#endif
+ op = be16_to_cpu(((struct mlx5_inbox_hdr *)in->first.data)->opcode);
+ if (op < ARRAY_SIZE(cmd->stats)) {
+ stats = &cmd->stats[op];
+@@ -1095,6 +1109,7 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
+ void *context;
+ int err;
+ int i;
++ ktime_t t1, t2, delta;
+ s64 ds;
+ struct mlx5_cmd_stats *stats;
+ unsigned long flags;
+@@ -1108,7 +1123,11 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
+ sem = &cmd->pages_sem;
+ else
+ sem = &cmd->sem;
++#ifdef HAVE_KTIME_GET_NS
+ ent->ts2 = ktime_get_ns();
++#else
++ ktime_get_ts(&ent->ts2);
++#endif
+ memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out));
+ dump_command(dev, ent, 0);
+ if (!ent->ret) {
+@@ -1122,7 +1141,14 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
+ }
+ free_ent(cmd, ent->idx);
+ if (ent->callback) {
++#ifdef HAVE_KTIME_GET_NS
+ ds = ent->ts2 - ent->ts1;
++#else
++ t1 = timespec_to_ktime(ent->ts1);
++ t2 = timespec_to_ktime(ent->ts2);
++ delta = ktime_sub(t2, t1);
++ ds = ktime_to_ns(delta);
++#endif
+ if (ent->op < ARRAY_SIZE(cmd->stats)) {
+ stats = &cmd->stats[ent->op];
+ spin_lock_irqsave(&stats->lock, flags);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+@@ -210,6 +210,9 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev)
+ struct mlx5_eq_table *table = &dev->priv.eq_table;
+ int num_eqs = 1 << dev->caps.gen.log_max_eq;
+ int nvec;
++#ifndef HAVE_PCI_ENABLE_MSIX_RANGE
++ int err;
++#endif
+ int i;
+
+ nvec = dev->caps.gen.num_ports * num_online_cpus() + MLX5_EQ_VEC_COMP_BASE;
+@@ -224,12 +227,26 @@ static int mlx5_enable_msix(struct mlx5_core_dev *dev)
+ for (i = 0; i < nvec; i++)
+ table->msix_arr[i].entry = i;
+
++#ifdef HAVE_PCI_ENABLE_MSIX_RANGE
+ nvec = pci_enable_msix_range(dev->pdev, table->msix_arr,
+ MLX5_EQ_VEC_COMP_BASE, nvec);
+ if (nvec < 0)
+ return nvec;
+
+ table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
++#else
++retry:
++ table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE;
++ err = pci_enable_msix(dev->pdev, table->msix_arr, nvec);
++ if (err <= 0) {
++ return err;
++ } else if (err > 2) {
++ nvec = err;
++ goto retry;
++ }
++
++ mlx5_core_dbg(dev, "received %d MSI vectors out of %d requested\n", err, nvec);
++#endif
+
+ return 0;
+ }
+diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/include/linux/mlx5/driver.h
++++ b/include/linux/mlx5/driver.h
+@@ -564,8 +564,13 @@ struct mlx5_cmd_work_ent {
+ int page_queue;
+ u8 status;
+ u8 token;
++#ifdef HAVE_KTIME_GET_NS
+ u64 ts1;
+ u64 ts2;
++#else
++ struct timespec ts1;
++ struct timespec ts2;
++#endif
+ u16 op;
+ };
+
--- /dev/null
+From: Vladimir Sokolovsky <vlad@mellanox.com>
+Subject: [PATCH] BACKPORT: mlx4 core and en
+
+Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
+---
+ drivers/net/ethernet/mellanox/mlx4/cmd.c | 6 +++
+ drivers/net/ethernet/mellanox/mlx4/en_clock.c | 2 +
+ drivers/net/ethernet/mellanox/mlx4/en_cq.c | 5 ++
+ drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 9 ++++-
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 26 ++++++++++++
+ drivers/net/ethernet/mellanox/mlx4/en_rx.c | 48 ++++++++++++++++++++++-
+ drivers/net/ethernet/mellanox/mlx4/en_tx.c | 35 ++++++++++++++++-
+ drivers/net/ethernet/mellanox/mlx4/eq.c | 10 +++++
+ drivers/net/ethernet/mellanox/mlx4/main.c | 24 +++++++++++
+ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 4 ++
+ 10 files changed, 165 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
++++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
+@@ -2545,15 +2545,20 @@ int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_in
+
+ ivf->vlan = s_info->default_vlan;
+ ivf->qos = s_info->default_qos;
++#ifdef HAVE_TX_RATE_LIMIT
+ ivf->max_tx_rate = s_info->tx_rate;
+ ivf->min_tx_rate = 0;
++#endif
+ ivf->spoofchk = s_info->spoofchk;
++#ifdef HAVE_LINKSTATE
+ ivf->linkstate = s_info->link_state;
++#endif
+
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(mlx4_get_vf_config);
+
++#ifdef HAVE_LINKSTATE
+ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state)
+ {
+ struct mlx4_priv *priv = mlx4_priv(dev);
+@@ -2601,6 +2606,7 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state);
++#endif
+
+ int mlx4_vf_smi_enabled(struct mlx4_dev *dev, int slave, int port)
+ {
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+@@ -276,7 +276,9 @@ static const struct ptp_clock_info mlx4_en_ptp_clock_info = {
+ .n_alarm = 0,
+ .n_ext_ts = 0,
+ .n_per_out = 0,
++#ifdef HAVE_PTP_CLOCK_INFO_N_PINS
+ .n_pins = 0,
++#endif
+ .pps = 0,
+ .adjfreq = mlx4_en_phc_adjfreq,
+ .adjtime = mlx4_en_phc_adjtime,
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+@@ -34,6 +34,7 @@
+ #include <linux/mlx4/cq.h>
+ #include <linux/mlx4/qp.h>
+ #include <linux/mlx4/cmd.h>
++#include <linux/interrupt.h>
+
+ #include "mlx4_en.h"
+
+@@ -176,7 +177,9 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+ mlx4_warn(mdev, "Failed setting affinity hint\n");
+
+ netif_napi_add(cq->dev, &cq->napi, mlx4_en_poll_rx_cq, 64);
++#ifdef HAVE_NAPI_HASH_ADD
+ napi_hash_add(&cq->napi);
++#endif
+ }
+
+ napi_enable(&cq->napi);
+@@ -205,8 +208,10 @@ void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+ {
+ napi_disable(&cq->napi);
+ if (!cq->is_tx) {
++#ifdef HAVE_NAPI_HASH_ADD
+ napi_hash_del(&cq->napi);
+ synchronize_rcu();
++#endif
+ irq_set_affinity_hint(cq->mcq.irq, NULL);
+ }
+ netif_napi_del(&cq->napi);
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+@@ -580,6 +580,7 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
+ param->tx_pending = priv->tx_ring[0]->size;
+ }
+
++#ifdef HAVE_GET_SET_RXFH
+ static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
+ {
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+@@ -650,6 +651,7 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
+ mutex_unlock(&mdev->state_lock);
+ return err;
+ }
++#endif
+
+ #define all_zeros_or_all_ones(field) \
+ ((field) == 0 || (field) == (__force typeof(field))-1)
+@@ -1267,6 +1269,7 @@ static u32 mlx4_en_get_priv_flags(struct net_device *dev)
+ return priv->pflags;
+ }
+
++#ifdef HAVE_GET_SET_TUNABLE
+ static int mlx4_en_get_tunable(struct net_device *dev,
+ const struct ethtool_tunable *tuna,
+ void *data)
+@@ -1308,7 +1311,7 @@ static int mlx4_en_set_tunable(struct net_device *dev,
+
+ return ret;
+ }
+-
++#endif
+
+ const struct ethtool_ops mlx4_en_ethtool_ops = {
+ .get_drvinfo = mlx4_en_get_drvinfo,
+@@ -1331,16 +1334,20 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
+ .set_ringparam = mlx4_en_set_ringparam,
+ .get_rxnfc = mlx4_en_get_rxnfc,
+ .set_rxnfc = mlx4_en_set_rxnfc,
++#ifdef HAVE_GET_SET_RXFH
+ .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
+ .get_rxfh = mlx4_en_get_rxfh,
+ .set_rxfh = mlx4_en_set_rxfh,
++#endif
+ .get_channels = mlx4_en_get_channels,
+ .set_channels = mlx4_en_set_channels,
+ .get_ts_info = mlx4_en_get_ts_info,
+ .set_priv_flags = mlx4_en_set_priv_flags,
+ .get_priv_flags = mlx4_en_get_priv_flags,
++#ifdef HAVE_GET_SET_TUNABLE
+ .get_tunable = mlx4_en_get_tunable,
+ .set_tunable = mlx4_en_set_tunable,
++#endif
+ };
+
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+@@ -38,8 +38,12 @@
+ #include <linux/slab.h>
+ #include <linux/hash.h>
+ #include <net/ip.h>
++#ifdef HAVE_SKB_MARK_NAPI_ID
+ #include <net/busy_poll.h>
++#endif
++#ifdef CONFIG_MLX4_EN_VXLAN
+ #include <net/vxlan.h>
++#endif
+
+ #include <linux/mlx4/driver.h>
+ #include <linux/mlx4/device.h>
+@@ -2107,7 +2111,11 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
+ return 0;
+ }
+
++#ifdef HAVE_SIOCGHWTSTAMP
+ static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
++#else
++static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
++#endif
+ {
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+@@ -2166,6 +2174,7 @@ static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
+ sizeof(config)) ? -EFAULT : 0;
+ }
+
++#ifdef HAVE_SIOCGHWTSTAMP
+ static int mlx4_en_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
+ {
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+@@ -2173,14 +2182,19 @@ static int mlx4_en_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
+ return copy_to_user(ifr->ifr_data, &priv->hwtstamp_config,
+ sizeof(priv->hwtstamp_config)) ? -EFAULT : 0;
+ }
++#endif
+
+ static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ switch (cmd) {
+ case SIOCSHWTSTAMP:
++#ifdef HAVE_SIOCGHWTSTAMP
+ return mlx4_en_hwtstamp_set(dev, ifr);
+ case SIOCGHWTSTAMP:
+ return mlx4_en_hwtstamp_get(dev, ifr);
++#else
++ return mlx4_en_hwtstamp_ioctl(dev, ifr);
++#endif
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -2239,6 +2253,7 @@ static int mlx4_en_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_
+ return mlx4_get_vf_config(mdev->dev, en_priv->port, vf, ivf);
+ }
+
++#ifdef HAVE_LINKSTATE
+ static int mlx4_en_set_vf_link_state(struct net_device *dev, int vf, int link_state)
+ {
+ struct mlx4_en_priv *en_priv = netdev_priv(dev);
+@@ -2246,7 +2261,9 @@ static int mlx4_en_set_vf_link_state(struct net_device *dev, int vf, int link_st
+
+ return mlx4_set_vf_link_state(mdev->dev, en_priv->port, vf, link_state);
+ }
++#endif
+
++#ifdef HAVE_NETDEV_PHYS_PORT_ID
+ #define PORT_ID_BYTE_LEN 8
+ static int mlx4_en_get_phys_port_id(struct net_device *dev,
+ struct netdev_phys_port_id *ppid)
+@@ -2266,6 +2283,7 @@ static int mlx4_en_get_phys_port_id(struct net_device *dev,
+ }
+ return 0;
+ }
++#endif
+
+ #ifdef CONFIG_MLX4_EN_VXLAN
+ static void mlx4_en_add_vxlan_offloads(struct work_struct *work)
+@@ -2369,7 +2387,9 @@ static const struct net_device_ops mlx4_netdev_ops = {
+ #ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = mlx4_en_low_latency_recv,
+ #endif
++#ifdef HAVE_NETDEV_PHYS_PORT_ID
+ .ndo_get_phys_port_id = mlx4_en_get_phys_port_id,
++#endif
+ #ifdef CONFIG_MLX4_EN_VXLAN
+ .ndo_add_vxlan_port = mlx4_en_add_vxlan_port,
+ .ndo_del_vxlan_port = mlx4_en_del_vxlan_port,
+@@ -2392,7 +2412,9 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
+ .ndo_set_vf_mac = mlx4_en_set_vf_mac,
+ .ndo_set_vf_vlan = mlx4_en_set_vf_vlan,
+ .ndo_set_vf_spoofchk = mlx4_en_set_vf_spoofchk,
++#ifdef HAVE_LINKSTATE
+ .ndo_set_vf_link_state = mlx4_en_set_vf_link_state,
++#endif
+ .ndo_get_vf_config = mlx4_en_get_vf_config,
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = mlx4_en_netpoll,
+@@ -2402,7 +2424,9 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
+ #ifdef CONFIG_RFS_ACCEL
+ .ndo_rx_flow_steer = mlx4_en_filter_rfs,
+ #endif
++#ifdef HAVE_NETDEV_PHYS_PORT_ID
+ .ndo_get_phys_port_id = mlx4_en_get_phys_port_id,
++#endif
+ };
+
+ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+@@ -2423,7 +2447,9 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+ netif_set_real_num_rx_queues(dev, prof->rx_ring_num);
+
+ SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev);
++#ifdef HAVE_NET_DEVICE_DEV_PORT
+ dev->dev_port = port - 1;
++#endif
+
+ /*
+ * Initialize driver private data
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+@@ -30,8 +30,9 @@
+ * SOFTWARE.
+ *
+ */
+-
++#ifdef HAVE_SKB_MARK_NAPI_ID
+ #include <net/busy_poll.h>
++#endif
+ #include <linux/mlx4/cq.h>
+ #include <linux/slab.h>
+ #include <linux/mlx4/qp.h>
+@@ -588,7 +589,9 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
+ skb_copy_to_linear_data(skb, va, length);
+ skb->tail += length;
+ } else {
++#ifdef HAVE_ETH_GET_HEADLEN
+ unsigned int pull_len;
++#endif
+
+ /* Move relevant fragments to skb */
+ used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, frags,
+@@ -599,7 +602,8 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
+ }
+ skb_shinfo(skb)->nr_frags = used_frags;
+
+- pull_len = eth_get_headlen(va, SMALL_PACKET_SIZE);
++#ifdef HAVE_ETH_GET_HEADLEN
++ pull_len = eth_get_headlen(va, SMALLl_PACKET_SIZE);
+ /* Copy headers into the skb linear buffer */
+ memcpy(skb->data, va, pull_len);
+ skb->tail += pull_len;
+@@ -610,6 +614,17 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
+ /* Adjust size of first fragment */
+ skb_frag_size_sub(&skb_shinfo(skb)->frags[0], pull_len);
+ skb->data_len = length - pull_len;
++#else
++ memcpy(skb->data, va, HEADER_COPY_SIZE);
++ skb->tail += HEADER_COPY_SIZE;
++
++ /* Skip headers in first fragment */
++ skb_shinfo(skb)->frags[0].page_offset += HEADER_COPY_SIZE;
++
++ /* Adjust size of first fragment */
++ skb_frag_size_sub(&skb_shinfo(skb)->frags[0], HEADER_COPY_SIZE);
++ skb->data_len = length - HEADER_COPY_SIZE;
++#endif
+ }
+ return skb;
+ }
+@@ -754,8 +769,12 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+ * - not an IP fragment
+ * - no LLS polling in progress
+ */
++#ifdef HAVE_SKB_MARK_NAPI_ID
+ if (!mlx4_en_cq_busy_polling(cq) &&
+ (dev->features & NETIF_F_GRO)) {
++#else
++ if (dev->features & NETIF_F_GRO) {
++#endif
+ struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
+ if (!gro_skb)
+ goto next;
+@@ -772,7 +791,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+ gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ if (l2_tunnel)
++#ifdef HAVE_SK_BUFF_CSUM_LEVEL
+ gro_skb->csum_level = 1;
++#else
++ gro_skb->encapsulation = 1;
++#endif
+ if ((cqe->vlan_my_qpn &
+ cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) &&
+ (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
+@@ -782,12 +805,18 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+ }
+
+ if (dev->features & NETIF_F_RXHASH)
++#ifdef HAVE_SKB_SET_HASH
+ skb_set_hash(gro_skb,
+ be32_to_cpu(cqe->immed_rss_invalid),
+ PKT_HASH_TYPE_L3);
++#else
++ gro_skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid);
++#endif
+
+ skb_record_rx_queue(gro_skb, cq->ring);
++#ifdef HAVE_SKB_MARK_NAPI_ID
+ skb_mark_napi_id(gro_skb, &cq->napi);
++#endif
+
+ if (ring->hwtstamp_rx_filter == HWTSTAMP_FILTER_ALL) {
+ timestamp = mlx4_en_get_cqe_ts(cqe);
+@@ -826,13 +855,22 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+ skb->protocol = eth_type_trans(skb, dev);
+ skb_record_rx_queue(skb, cq->ring);
+
++#ifdef HAVE_SK_BUFF_CSUM_LEVEL
+ if (l2_tunnel && ip_summed == CHECKSUM_UNNECESSARY)
+ skb->csum_level = 1;
++#else
++ if (l2_tunnel)
++ skb->encapsulation = 1;
++#endif
+
++#ifdef HAVE_SKB_SET_HASH
+ if (dev->features & NETIF_F_RXHASH)
+ skb_set_hash(skb,
+ be32_to_cpu(cqe->immed_rss_invalid),
+ PKT_HASH_TYPE_L3);
++#else
++ skb->rxhash = be32_to_cpu(cqe->immed_rss_invalid);
++#endif
+
+ if ((be32_to_cpu(cqe->vlan_my_qpn) &
+ MLX4_CQE_VLAN_PRESENT_MASK) &&
+@@ -845,7 +883,9 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
+ timestamp);
+ }
+
++#ifdef HAVE_SKB_MARK_NAPI_ID
+ skb_mark_napi_id(skb, &cq->napi);
++#endif
+
+ if (!mlx4_en_cq_busy_polling(cq))
+ napi_gro_receive(&cq->napi, skb);
+@@ -893,12 +933,16 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int done;
+
++#ifdef HAVE_SKB_MARK_NAPI_ID
+ if (!mlx4_en_cq_lock_napi(cq))
+ return budget;
++#endif
+
+ done = mlx4_en_process_rx_cq(dev, cq, budget);
+
++#ifdef HAVE_SKB_MARK_NAPI_ID
+ mlx4_en_cq_unlock_napi(cq);
++#endif
+
+ /* If we used up all the quota - we're probably not done yet... */
+ if (done == budget) {
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+@@ -151,7 +151,11 @@ err_bounce:
+ kfree(ring->bounce_buf);
+ ring->bounce_buf = NULL;
+ err_info:
++#ifdef HAVE_KVFREE
+ kvfree(ring->tx_info);
++#else
++ vfree(ring->tx_info);
++#endif
+ ring->tx_info = NULL;
+ err_ring:
+ kfree(ring);
+@@ -174,7 +178,11 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+ kfree(ring->bounce_buf);
+ ring->bounce_buf = NULL;
++#ifdef HAVE_KVFREE
+ kvfree(ring->tx_info);
++#else
++ vfree(ring->tx_info);
++#endif
+ ring->tx_info = NULL;
+ kfree(ring);
+ *pring = NULL;
+@@ -328,7 +336,11 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
+ }
+ }
+ }
++#ifdef HAVE_DEV_CONSUME_SKB_ANY
+ dev_consume_skb_any(skb);
++#else
++ dev_kfree_skb_any(skb);
++#endif
+ return tx_info->nr_txbb;
+ }
+
+@@ -392,7 +404,11 @@ static bool mlx4_en_process_tx_cq(struct net_device *dev,
+ if (!priv->port_up)
+ return true;
+
++#ifdef HAVE_NETDEV_TXQ_BQL_PREFETCHW
+ netdev_txq_bql_complete_prefetchw(ring->tx_queue);
++#else
++ prefetchw(&ring->tx_queue->dql.limit);
++#endif
+
+ index = cons_index & size_mask;
+ cqe = mlx4_en_get_cqe(buf, index, priv->cqe_size) + factor;
+@@ -665,7 +681,11 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc,
+ }
+
+ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
++#ifdef HAVE_SELECT_QUEUE_FALLBACK_T
+ void *accel_priv, select_queue_fallback_t fallback)
++#else
++ void *accel_priv)
++#endif
+ {
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ u16 rings_p_up = priv->num_tx_rings_p_up;
+@@ -677,7 +697,11 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+ if (vlan_tx_tag_present(skb))
+ up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT;
+
++#ifdef HAVE_SELECT_QUEUE_FALLBACK_T
+ return fallback(dev, skb) % rings_p_up + up * rings_p_up;
++#else
++ return __netdev_pick_tx(dev, skb) % rings_p_up + up * rings_p_up;
++#endif
+ }
+
+ static void mlx4_bf_copy(void __iomem *dst, const void *src,
+@@ -737,8 +761,11 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
+ if (vlan_tx_tag_present(skb))
+ vlan_tag = vlan_tx_tag_get(skb);
+
+-
++#ifdef HAVE_NETDEV_TXQ_BQL_PREFETCHW
+ netdev_txq_bql_enqueue_prefetchw(ring->tx_queue);
++#else
++ prefetchw(&ring->tx_queue->dql);
++#endif
+
+ /* Track current inflight packets for performance analysis */
+ AVG_PERF_COUNTER(priv->pstats.inflight_avg,
+@@ -914,7 +941,11 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
+ netif_tx_stop_queue(ring->tx_queue);
+ ring->queue_stopped++;
+ }
++#ifdef HAVE_SK_BUFF_XMIT_MORE
+ send_doorbell = !skb->xmit_more || netif_xmit_stopped(ring->tx_queue);
++#else
++ send_doorbell = 1;
++#endif
+
+ real_size = (real_size / 16) & 0x3f;
+
+@@ -953,8 +984,10 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
+ wmb();
+ iowrite32(ring->doorbell_qpn,
+ ring->bf.uar->map + MLX4_SEND_DOORBELL);
++#ifdef HAVE_SK_BUFF_XMIT_MORE
+ } else {
+ ring->xmit_more++;
++#endif
+ }
+ }
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
++++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
+@@ -461,7 +461,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
+ int i;
+ enum slave_port_gen_event gen_event;
+ unsigned long flags;
++#ifdef HAVE_LINKSTATE
+ struct mlx4_vport_state *s_info;
++#endif
+ int eqe_size = dev->caps.eqe_size;
+
+ while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor, eqe_size))) {
+@@ -568,6 +570,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
+ continue;
+ mlx4_dbg(dev, "%s: Sending MLX4_PORT_CHANGE_SUBTYPE_DOWN to slave: %d, port:%d\n",
+ __func__, i, port);
++#ifdef HAVE_LINKSTATE
+ s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
+ if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) {
+ eqe->event.port_change.port =
+@@ -576,6 +579,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
+ | (mlx4_phys_to_slave_port(dev, i, port) << 28));
+ mlx4_slave_event(dev, i, eqe);
+ }
++#else
++ mlx4_slave_event(dev, i, eqe);
++#endif
+ } else { /* IB port */
+ set_and_calc_slave_port_state(dev, i, port,
+ MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN,
+@@ -601,6 +607,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
+ continue;
+ if (i == mlx4_master_func_num(dev))
+ continue;
++#ifdef HAVE_LINKSTATE
+ s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
+ if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) {
+ eqe->event.port_change.port =
+@@ -609,6 +616,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
+ | (mlx4_phys_to_slave_port(dev, i, port) << 28));
+ mlx4_slave_event(dev, i, eqe);
+ }
++#else
++ mlx4_slave_event(dev, i, eqe);
++#endif
+ }
+ else /* IB port */
+ /* port-up event will be sent to a slave when the
+diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/main.c
++++ b/drivers/net/ethernet/mellanox/mlx4/main.c
+@@ -2057,6 +2057,9 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
+ int nreq = min_t(int, dev->caps.num_ports *
+ min_t(int, num_online_cpus() + 1,
+ MAX_MSIX_P_PORT) + MSIX_LEGACY_SZ, MAX_MSIX);
++#ifndef HAVE_PCI_ENABLE_MSIX_RANGE
++ int err;
++#endif
+ int i;
+
+ if (msi_x) {
+@@ -2070,6 +2073,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
+ for (i = 0; i < nreq; ++i)
+ entries[i].entry = i;
+
++
++#ifdef HAVE_PCI_ENABLE_MSIX_RANGE
+ nreq = pci_enable_msix_range(dev->pdev, entries, 2, nreq);
+
+ if (nreq < 0) {
+@@ -2077,6 +2082,25 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
+ goto no_msi;
+ } else if (nreq < MSIX_LEGACY_SZ +
+ dev->caps.num_ports * MIN_MSIX_P_PORT) {
++#else
++ retry:
++ err = pci_enable_msix(dev->pdev, entries, nreq);
++ if (err) {
++ /* Try again if at least 2 vectors are available */
++ if (err > 1) {
++ mlx4_info(dev, "Requested %d vectors, "
++ "but only %d MSI-X vectors available, "
++ "trying again\n", nreq, err);
++ nreq = err;
++ goto retry;
++ }
++ kfree(entries);
++ goto no_msi;
++ }
++
++ if (nreq <
++ MSIX_LEGACY_SZ + dev->caps.num_ports * MIN_MSIX_P_PORT) {
++#endif
+ /*Working in legacy mode , all EQ's shared*/
+ dev->caps.comp_pool = 0;
+ dev->caps.num_comp_vectors = nreq - 1;
+diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+index xxxxxxx..xxxxxxx xxxxxx
+--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
++++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+@@ -764,7 +764,11 @@ int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+
+ void mlx4_en_tx_irq(struct mlx4_cq *mcq);
+ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
++#ifdef HAVE_SELECT_QUEUE_FALLBACK_T
+ void *accel_priv, select_queue_fallback_t fallback);
++#else
++ void *accel_priv);
++#endif
+ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
+
+ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,