]> git.openfabrics.org - ~emulex/compat-rdma.git/commitdiff
be2net backport patch
authorSelvin Xavier <selvin.xavier@emulex.com>
Fri, 5 Dec 2014 18:31:50 +0000 (10:31 -0800)
committerSelvin Xavier <selvin.xavier@emulex.com>
Fri, 5 Dec 2014 18:31:50 +0000 (10:31 -0800)
Signed-off-by: Selvin Xavier <selvin.xavier@emulex.com>
patches/0021-be2net-backport-patch.patch [new file with mode: 0644]

diff --git a/patches/0021-be2net-backport-patch.patch b/patches/0021-be2net-backport-patch.patch
new file mode 100644 (file)
index 0000000..110fcdb
--- /dev/null
@@ -0,0 +1,1067 @@
+From dc3cc69f6acb3891404cd46300a2934511b605ef Mon Sep 17 00:00:00 2001
+From: Selvin Xavier <selvin.xavier@emulex.com>
+Date: Sat, 6 Dec 2014 15:16:41 +0530
+Subject: [PATCH 1/2] be2net: backport patch 
+
+Signed-off-by: Selvin Xavier <selvin.xavier@emulex.com>
+---
+ drivers/net/ethernet/emulex/benet/Makefile     |    2 +-
+ drivers/net/ethernet/emulex/benet/be.h         |   10 +-
+ drivers/net/ethernet/emulex/benet/be_cmds.c    |    6 +-
+ drivers/net/ethernet/emulex/benet/be_compat.c  |   74 +++++++
+ drivers/net/ethernet/emulex/benet/be_compat.h  |  126 +++++++++++
+ drivers/net/ethernet/emulex/benet/be_ethtool.c |   43 +++-
+ drivers/net/ethernet/emulex/benet/be_main.c    |  271 +++++++++++++++++++++---
+ 7 files changed, 492 insertions(+), 40 deletions(-)
+ create mode 100644 drivers/net/ethernet/emulex/benet/be_compat.c
+ create mode 100644 drivers/net/ethernet/emulex/benet/be_compat.h
+
+diff --git a/drivers/net/ethernet/emulex/benet/Makefile b/drivers/net/ethernet/emulex/benet/Makefile
+index 1a91b27..a32863b 100644
+--- a/drivers/net/ethernet/emulex/benet/Makefile
++++ b/drivers/net/ethernet/emulex/benet/Makefile
+@@ -4,4 +4,4 @@
+ obj-$(CONFIG_BE2NET) += be2net.o
+-be2net-y :=  be_main.o be_cmds.o be_ethtool.o be_roce.o
++be2net-y :=  be_main.o be_cmds.o be_ethtool.o be_roce.o be_compat.o
+diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
+index 9a2d752..fff6982 100644
+--- a/drivers/net/ethernet/emulex/benet/be.h
++++ b/drivers/net/ethernet/emulex/benet/be.h
+@@ -20,6 +20,7 @@
+ #include <linux/pci.h>
+ #include <linux/etherdevice.h>
++#include <linux/version.h>
+ #include <linux/delay.h>
+ #include <net/tcp.h>
+ #include <net/ip.h>
+@@ -30,11 +31,13 @@
+ #include <linux/firmware.h>
+ #include <linux/slab.h>
+ #include <linux/u64_stats_sync.h>
++#include <linux/netdevice.h>
+ #include "be_hw.h"
+ #include "be_roce.h"
++#include "be_compat.h"
+-#define DRV_VER                       "10.4u"
++#define DRV_VER                       "10.4u_ofed"
+ #define DRV_NAME              "be2net"
+ #define BE_NAME                       "Emulex BladeEngine2"
+ #define BE3_NAME              "Emulex BladeEngine3"
+@@ -508,7 +511,9 @@ struct be_adapter {
+       u32 num_msix_roce_vec;
+       struct ocrdma_dev *ocrdma_dev;
+       struct list_head entry;
+-
++#ifndef HAVE_NDO_GET_STATS64
++      struct net_device_stats net_stats;
++#endif
+       u32 flash_status;
+       struct completion et_cmd_compl;
+@@ -532,6 +537,7 @@ struct be_adapter {
+       int be_get_temp_freq;
+       u8 pf_number;
+       struct rss_info rss_info;
++      struct vlan_group *vlan_grp;
+ };
+ #define be_physfn(adapter)            (!adapter->virtfn)
+diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
+index fead5c6..1d12f49 100644
+--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
++++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
+@@ -1920,7 +1920,11 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
+                       req->if_flags =
+                               cpu_to_le32(BE_IF_FLAGS_VLAN_PROMISCUOUS);
+       } else {
++#ifdef HAVE_NETDEV_HW_ADDR
+               struct netdev_hw_addr *ha;
++#else
++              struct dev_addr_list *ha;
++#endif
+               int i = 0;
+               req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_MULTICAST);
+@@ -1934,7 +1938,7 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
+                                   be_if_cap_flags(adapter));
+               req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
+               netdev_for_each_mc_addr(ha, adapter->netdev)
+-                      memcpy(req->mcast_mac[i++].byte, ha->addr, ETH_ALEN);
++                      memcpy(req->mcast_mac[i++].byte, ha->DMI_ADDR, ETH_ALEN);
+       }
+       if ((req->if_flags_mask & cpu_to_le32(be_if_cap_flags(adapter))) !=
+diff --git a/drivers/net/ethernet/emulex/benet/be_compat.c b/drivers/net/ethernet/emulex/benet/be_compat.c
+new file mode 100644
+index 0000000..d1563d3
+--- /dev/null
++++ b/drivers/net/ethernet/emulex/benet/be_compat.c
+@@ -0,0 +1,74 @@
++#include "be.h"
++
++#if defined(CONFIG_PCI_IOV)
++#define sriov_kernel                            true
++#else
++#define sriov_kernel                            false
++#endif
++
++#ifndef PCI_DEV_FLAGS_ASSIGNED
++#define PCI_DEV_FLAGS_ASSIGNED 0x04
++#endif
++
++#ifdef CONFIG_PCI_IOV
++int be_find_vfs(struct pci_dev *pdev, int vf_state)
++{
++      struct pci_dev *dev = pdev;
++      int vfs = 0, assigned_vfs = 0, pos;
++
++      if (!sriov_kernel)
++              return 0;
++
++      pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
++      if (!pos)
++              return 0;
++
++      dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL);
++      while (dev) {
++              if (dev->is_virtfn && pci_physfn(dev) == pdev) {
++                      vfs++;
++                      if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)
++                              assigned_vfs++;
++              }
++              dev = pci_get_device(pdev->vendor, PCI_ANY_ID, dev);
++      }
++      return (vf_state == ASSIGNED) ? assigned_vfs : vfs;
++}
++
++#ifndef HAVE_PCI_VF_ASSIGNED
++/**
++ * pci_vfs_assigned - returns number of VFs are assigned to a guest
++ * @dev: the PCI device
++ *
++ * Returns number of VFs belonging to this device that are assigned to a guest.
++ * If device is not a physical function returns -ENODEV.
++ */
++int pci_vfs_assigned(struct pci_dev *pdev)
++{
++      return be_find_vfs(pdev, ASSIGNED);
++}
++
++/**
++ * pci_num_vf - return number of VFs associated with a PF device_release_driver
++ * @dev: the PCI device
++ *
++ * Returns number of VFs, or 0 if SR-IOV is not enabled.
++ */
++int pci_num_vf(struct pci_dev *pdev)
++{
++      return be_find_vfs(pdev, ENABLED);
++}
++
++int pci_sriov_get_totalvfs(struct pci_dev *pdev)
++{
++      u16 num = 0;
++      int pos;
++
++      pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
++      if (pos)
++              pci_read_config_word(pdev, pos + PCI_SRIOV_TOTAL_VF, &num);
++      return num;
++}
++
++#endif
++#endif /* CONFIG_PCI_IOV */
+diff --git a/drivers/net/ethernet/emulex/benet/be_compat.h b/drivers/net/ethernet/emulex/benet/be_compat.h
+new file mode 100644
+index 0000000..e6a94f7
+--- /dev/null
++++ b/drivers/net/ethernet/emulex/benet/be_compat.h
+@@ -0,0 +1,126 @@
++#ifndef BE_COMPAT_H
++#define BE_COMPAT_H
++
++#include <linux/netdevice.h>
++
++#ifndef VLAN_N_VID
++#define VLAN_N_VID              4096
++#endif
++
++#ifndef HAVE_VLAN_HWACCEL_RECEIVE_SKB
++#define USE_NEW_VLAN_MODEL
++#endif
++
++#if defined(USE_NEW_VLAN_MODEL) || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
++/* vlan_gro_frags() can be safely called when vlan_group is NULL
++ *  * for kernels >= 3.0 or when kernels uses USE_NEW_VLAN_MODEL.
++ */
++#define NULL_VLAN_GRP_SAFE
++#endif
++
++static inline struct sk_buff *__vlan_put_tag_fixed(struct sk_buff *skb,
++                                                 __be16 vlan_proto,
++                                                 ushort vlan_tag)
++{
++#ifdef HAVE_3_PARAMS_FOR_VLAN_PUT_TAG
++      struct sk_buff *new_skb = __vlan_put_tag(skb, vlan_proto, vlan_tag);
++#else
++      struct sk_buff *new_skb = __vlan_put_tag(skb, vlan_tag);
++#endif
++      return new_skb;
++}
++
++#ifdef USE_NEW_VLAN_MODEL
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
++struct vlan_group {
++      char dummy;
++};
++#endif
++
++static inline int vlan_hwaccel_receive_skb_compat(struct sk_buff *skb,
++                                                struct vlan_group *grp,
++                                                u16 vlan_tci)
++{
++#ifdef HAVE_3_PARAMS_FOR_VLAN_HWACCEL_PUT_TAG
++      __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
++#else
++      __vlan_hwaccel_put_tag(skb, vlan_tci);
++#endif
++      return netif_receive_skb(skb);
++}
++
++static inline gro_result_t vlan_gro_frags_compat(struct napi_struct *napi,
++                                               struct vlan_group *grp,
++                                               unsigned int vlan_tci)
++{
++#ifdef HAVE_3_PARAMS_FOR_VLAN_HWACCEL_PUT_TAG
++      __vlan_hwaccel_put_tag(napi->skb, htons(ETH_P_8021Q), vlan_tci);
++#else
++      __vlan_hwaccel_put_tag(napi->skb, vlan_tci);
++#endif
++      return napi_gro_frags(napi);
++}
++
++#define vlan_hwaccel_receive_skb                vlan_hwaccel_receive_skb_compat
++#define vlan_gro_frags                          vlan_gro_frags_compat
++#endif
++
++#ifdef CONFIG_PCI_IOV
++int be_find_vfs(struct pci_dev *pdev, int vf_state);
++#ifndef HAVE_PCI_VF_ASSIGNED
++int pci_vfs_assigned(struct pci_dev *pdev);
++int pci_num_vf(struct pci_dev *pdev);
++int pci_sriov_get_totalvfs(struct pci_dev *pdev);
++#endif
++#else
++#define pci_vfs_assigned(x)                     0
++#define pci_num_vf(x)                           0
++#endif /* CONFIG_PCI_IOV */
++
++#ifndef NETIF_F_HW_VLAN_CTAG_TX
++#define NETIF_F_HW_VLAN_CTAG_TX         NETIF_F_HW_VLAN_TX
++#endif
++#ifndef NETIF_F_HW_VLAN_CTAG_RX
++#define NETIF_F_HW_VLAN_CTAG_RX         NETIF_F_HW_VLAN_RX
++#endif
++#ifndef NETIF_F_HW_VLAN_CTAG_FILTER
++#define NETIF_F_HW_VLAN_CTAG_FILTER     NETIF_F_HW_VLAN_FILTER
++#endif
++
++#ifndef HAVE_NETDEV_HW_FEATURES
++#define hw_features                     features
++#endif
++
++#ifndef netdev_for_each_mc_addr
++#define netdev_for_each_mc_addr(h, n)   for (h = (n)->mc_list; h; h = h->next)
++#endif
++
++/* When new mc-list macros were used in 2.6.35, dev_mc_list was dropped */
++#ifdef HAVE_NETDEV_HW_ADDR
++#define DMI_ADDR                        addr
++#else
++#define DMI_ADDR                        dmi_addr
++#endif /* dev_mc_list */
++
++#ifndef DUPLEX_UNKNOWN
++#define DUPLEX_UNKNOWN 0xFF
++#endif
++
++#ifndef HAVE_ETHER_ADDR_COPY
++static inline void ether_addr_copy(u8 *dst, const u8 *src)
++{
++#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
++      *(u32 *)dst = *(const u32 *)src;
++      *(u16 *)(dst + 4) = *(const u16 *)(src + 4);
++#else
++      u16 *a = (u16 *)dst;
++      const u16 *b = (const u16 *)src;
++
++      a[0] = b[0];
++      a[1] = b[1];
++      a[2] = b[2];
++#endif
++}
++#endif
++
++#endif                          /* BE_COMPAT_H */
+diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
+index e42a791..04628fa 100644
+--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
+@@ -380,7 +380,11 @@ static void be_get_ethtool_stats(struct net_device *netdev,
+       struct be_rx_obj *rxo;
+       struct be_tx_obj *txo;
+       void *p;
+-      unsigned int i, j, base = 0, start;
++      unsigned int i, j, base = 0;
++      bool ret = false;
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++      unsigned int start;
++#endif
+       for (i = 0; i < ETHTOOL_STATS_NUM; i++) {
+               p = (u8 *)&adapter->drv_stats + et_stats[i].offset;
+@@ -392,10 +396,15 @@ static void be_get_ethtool_stats(struct net_device *netdev,
+               struct be_rx_stats *stats = rx_stats(rxo);
+               do {
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
+                       start = u64_stats_fetch_begin_irq(&stats->sync);
++#endif
+                       data[base] = stats->rx_bytes;
+                       data[base + 1] = stats->rx_pkts;
+-              } while (u64_stats_fetch_retry_irq(&stats->sync, start));
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = u64_stats_fetch_retry_irq(&stats->sync, start);
++#endif
++              } while (ret);
+               for (i = 2; i < ETHTOOL_RXSTATS_NUM; i++) {
+                       p = (u8 *)stats + et_rx_stats[i].offset;
+@@ -408,19 +417,31 @@ static void be_get_ethtool_stats(struct net_device *netdev,
+               struct be_tx_stats *stats = tx_stats(txo);
+               do {
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = false;
+                       start = u64_stats_fetch_begin_irq(&stats->sync_compl);
++#endif
+                       data[base] = stats->tx_compl;
+-              } while (u64_stats_fetch_retry_irq(&stats->sync_compl, start));
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = u64_stats_fetch_retry_irq(&stats->sync_compl, start);
++#endif
++              } while (ret);
+               do {
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = false;
+                       start = u64_stats_fetch_begin_irq(&stats->sync);
++#endif
+                       for (i = 1; i < ETHTOOL_TXSTATS_NUM; i++) {
+                               p = (u8 *)stats + et_tx_stats[i].offset;
+                               data[base + i] =
+                                       (et_tx_stats[i].size == sizeof(u64)) ?
+                                               *(u64 *)p : *(u32 *)p;
+                       }
+-              } while (u64_stats_fetch_retry_irq(&stats->sync, start));
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = u64_stats_fetch_retry_irq(&stats->sync, start);
++#endif
++              } while (ret);
+               base += ETHTOOL_TXSTATS_NUM;
+       }
+ }
+@@ -698,7 +719,6 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
+       be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);
+       ecmd->autoneg = adapter->phy.fc_autoneg;
+ }
+-
+ static int
+ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
+ {
+@@ -718,6 +738,7 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
+       return be_cmd_status(status);
+ }
++#ifdef HAVE_SET_PHYS_ID
+ static int be_set_phys_id(struct net_device *netdev,
+                         enum ethtool_phys_id_state state)
+ {
+@@ -746,6 +767,7 @@ static int be_set_phys_id(struct net_device *netdev,
+       return 0;
+ }
++#endif
+ static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump)
+ {
+@@ -1136,6 +1158,7 @@ static int be_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
+       return status;
+ }
++#ifdef HAVE_GET_SET_CHANNELS
+ static void be_get_channels(struct net_device *netdev,
+                           struct ethtool_channels *ch)
+ {
+@@ -1160,7 +1183,9 @@ static int be_set_channels(struct net_device  *netdev,
+       status = be_update_queues(adapter);
+       return be_cmd_status(status);
+ }
++#endif
++#ifdef HAVE_GET_SET_RXFH
+ static u32 be_get_rxfh_indir_size(struct net_device *netdev)
+ {
+       return RSS_INDIR_TABLE_LEN;
+@@ -1225,6 +1250,8 @@ static int be_set_rxfh(struct net_device *netdev, const u32 *indir,
+       return 0;
+ }
++#endif
++
+ static int be_get_module_info(struct net_device *netdev,
+                             struct ethtool_modinfo *modinfo)
+ {
+@@ -1291,7 +1318,9 @@ const struct ethtool_ops be_ethtool_ops = {
+       .get_pauseparam = be_get_pauseparam,
+       .set_pauseparam = be_set_pauseparam,
+       .get_strings = be_get_stat_strings,
++#ifdef HAVE_SET_PHYS_ID
+       .set_phys_id = be_set_phys_id,
++#endif
+       .set_dump = be_set_dump,
+       .get_msglevel = be_get_msg_level,
+       .set_msglevel = be_set_msg_level,
+@@ -1303,12 +1332,16 @@ const struct ethtool_ops be_ethtool_ops = {
+       .self_test = be_self_test,
+       .get_rxnfc = be_get_rxnfc,
+       .set_rxnfc = be_set_rxnfc,
++#ifdef HAVE_GET_SET_RXFH
+       .get_rxfh_indir_size = be_get_rxfh_indir_size,
+       .get_rxfh_key_size = be_get_rxfh_key_size,
+       .get_rxfh = be_get_rxfh,
+       .set_rxfh = be_set_rxfh,
++#endif
++#ifdef HAVE_GET_SET_CHANNELS
+       .get_channels = be_get_channels,
+       .set_channels = be_set_channels,
++#endif
+       .get_module_info = be_get_module_info,
+       .get_module_eeprom = be_get_module_eeprom
+ };
+diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
+index 3e8475c..916c4a3 100644
+--- a/drivers/net/ethernet/emulex/benet/be_main.c
++++ b/drivers/net/ethernet/emulex/benet/be_main.c
+@@ -143,8 +143,8 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
+       q->len = len;
+       q->entry_size = entry_size;
+       mem->size = len * entry_size;
+-      mem->va = dma_zalloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
+-                                    GFP_KERNEL);
++      mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
++                                    GFP_KERNEL|__GFP_ZERO);
+       if (!mem->va)
+               return -ENOMEM;
+       return 0;
+@@ -579,6 +579,76 @@ void be_parse_stats(struct be_adapter *adapter)
+       }
+ }
++#ifndef HAVE_NDO_GET_STATS64
++static void be_get_error_stats(struct be_adapter *adapter,
++                             struct net_device_stats *stats)
++{
++      struct be_drv_stats *drvs = &adapter->drv_stats;
++
++      /* bad pkts received */
++      stats->rx_errors = drvs->rx_crc_errors +
++              drvs->rx_alignment_symbol_errors +
++              drvs->rx_in_range_errors +
++              drvs->rx_out_range_errors +
++              drvs->rx_frame_too_long +
++              drvs->rx_dropped_too_small +
++              drvs->rx_dropped_too_short +
++              drvs->rx_dropped_header_too_small +
++              drvs->rx_dropped_tcp_length +
++              drvs->rx_dropped_runt;
++
++      /* detailed rx errors */
++      stats->rx_length_errors = drvs->rx_in_range_errors +
++              drvs->rx_out_range_errors +
++              drvs->rx_frame_too_long;
++
++      stats->rx_crc_errors = drvs->rx_crc_errors;
++
++      /* frame alignment errors */
++      stats->rx_frame_errors = drvs->rx_alignment_symbol_errors;
++
++      /* receiver fifo overrun */
++      /* drops_no_pbuf is no per i/f, it's per BE card */
++      stats->rx_fifo_errors = drvs->rxpp_fifo_overflow_drop +
++              drvs->rx_input_fifo_overflow_drop +
++              drvs->rx_drops_no_pbuf;
++}
++
++static struct net_device_stats *be_get_stats(struct net_device *dev)
++{
++      struct be_adapter *adapter = netdev_priv(dev);
++      struct net_device_stats *stats = &adapter->net_stats;
++      struct be_rx_obj *rxo;
++      struct be_tx_obj *txo;
++      unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0;
++      int i;
++
++      for_all_rx_queues(adapter, rxo, i) {
++              pkts += rx_stats(rxo)->rx_pkts;
++              bytes += rx_stats(rxo)->rx_bytes;
++              mcast += rx_stats(rxo)->rx_mcast_pkts;
++              drops += rx_stats(rxo)->rx_drops_no_skbs +
++                      rx_stats(rxo)->rx_drops_no_frags;
++      }
++      stats->rx_packets = pkts;
++      stats->rx_bytes = bytes;
++      stats->multicast = mcast;
++      stats->rx_dropped = drops;
++
++      pkts = 0;
++      bytes = 0;
++      for_all_tx_queues(adapter, txo, i) {
++              pkts += tx_stats(txo)->tx_pkts;
++              bytes += tx_stats(txo)->tx_bytes;
++      }
++      stats->tx_packets = pkts;
++      stats->tx_bytes = bytes;
++
++      be_get_error_stats(adapter, stats);
++
++      return stats;
++}
++#else
+ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
+                                               struct rtnl_link_stats64 *stats)
+ {
+@@ -587,17 +657,25 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
+       struct be_rx_obj *rxo;
+       struct be_tx_obj *txo;
+       u64 pkts, bytes;
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
+       unsigned int start;
++      bool ret = false;
++#endif
+       int i;
+       for_all_rx_queues(adapter, rxo, i) {
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
+               const struct be_rx_stats *rx_stats = rx_stats(rxo);
+               do {
+                       start = u64_stats_fetch_begin_irq(&rx_stats->sync);
++#endif
+                       pkts = rx_stats(rxo)->rx_pkts;
+                       bytes = rx_stats(rxo)->rx_bytes;
+-              } while (u64_stats_fetch_retry_irq(&rx_stats->sync, start));
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++              ret = u64_stats_fetch_retry_irq(&rx_stats->sync, start)
++              } while (ret);
++#endif
+               stats->rx_packets += pkts;
+               stats->rx_bytes += bytes;
+               stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+@@ -606,13 +684,19 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
+       }
+       for_all_tx_queues(adapter, txo, i) {
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
+               const struct be_tx_stats *tx_stats = tx_stats(txo);
+               do {
++                      ret = false;
+                       start = u64_stats_fetch_begin_irq(&tx_stats->sync);
++#endif
+                       pkts = tx_stats(txo)->tx_pkts;
+                       bytes = tx_stats(txo)->tx_bytes;
+-              } while (u64_stats_fetch_retry_irq(&tx_stats->sync, start));
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = u64_stats_fetch_retry_irq(&tx_stats->sync, start);
++              } while (ret);
++#endif
+               stats->tx_packets += pkts;
+               stats->tx_bytes += bytes;
+       }
+@@ -646,6 +730,7 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
+                               drvs->rx_drops_no_pbuf;
+       return stats;
+ }
++#endif
+ void be_link_status_update(struct be_adapter *adapter, u8 link_status)
+ {
+@@ -887,7 +972,7 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
+       }
+       if (vlan_tag) {
+-              skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
++              skb = __vlan_put_tag_fixed(skb, htons(ETH_P_8021Q), vlan_tag);
+               if (unlikely(!skb))
+                       return skb;
+               skb->vlan_tci = 0;
+@@ -896,7 +981,7 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
+       /* Insert the outer VLAN, if any */
+       if (adapter->qnq_vid) {
+               vlan_tag = adapter->qnq_vid;
+-              skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
++              skb = __vlan_put_tag_fixed(skb, htons(ETH_P_8021Q), vlan_tag);
+               if (unlikely(!skb))
+                       return skb;
+               if (skip_hw_vlan)
+@@ -1152,17 +1237,29 @@ set_vlan_promisc:
+       return status;
+ }
++#ifdef HAVE_NDO_RX_ADD_VID_HAS_3_PARAMS
+ static int be_vlan_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
++#else
++static void be_vlan_add_vid(struct net_device *netdev,  u16 vid)
++#endif
+ {
+       struct be_adapter *adapter = netdev_priv(netdev);
+       int status = 0;
+       /* Packets with VID 0 are always received by Lancer by default */
+       if (lancer_chip(adapter) && vid == 0)
++#ifdef HAVE_NDO_RX_ADD_VID_HAS_3_PARAMS
+               return status;
++#else
++      return;
++#endif
+       if (test_bit(vid, adapter->vids))
++#ifdef HAVE_NDO_RX_ADD_VID_HAS_3_PARAMS
+               return status;
++#else
++              return;
++#endif
+       set_bit(vid, adapter->vids);
+       adapter->vlans_added++;
+@@ -1173,21 +1270,39 @@ static int be_vlan_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
+               clear_bit(vid, adapter->vids);
+       }
+-      return status;
++#ifdef HAVE_NDO_RX_ADD_VID_HAS_3_PARAMS
++              return status;
++#else
++              return;
++#endif
+ }
++#ifdef HAVE_NDO_RX_ADD_VID_HAS_3_PARAMS
+ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
++#else
++static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
++#endif
+ {
++      int status = 0;
+       struct be_adapter *adapter = netdev_priv(netdev);
+       /* Packets with VID 0 are always received by Lancer by default */
+       if (lancer_chip(adapter) && vid == 0)
++#ifdef HAVE_NDO_RX_ADD_VID_HAS_3_PARAMS
+               return 0;
+-
++#else
++              return;
++#endif
+       clear_bit(vid, adapter->vids);
+       adapter->vlans_added--;
+-      return be_vid_config(adapter);
++      status = be_vid_config(adapter);
++
++#ifdef HAVE_NDO_RX_ADD_VID_HAS_3_PARAMS
++              return status;
++#else
++              return;
++#endif
+ }
+ static void be_clear_promisc(struct be_adapter *adapter)
+@@ -1318,8 +1433,10 @@ static int be_get_vf_config(struct net_device *netdev, int vf,
+               return -EINVAL;
+       vi->vf = vf;
++#ifdef HAVE_TX_RATE_LIMI
+       vi->max_tx_rate = vf_cfg->tx_rate;
+       vi->min_tx_rate = 0;
++#endif
+       vi->vlan = vf_cfg->vlan_tag & VLAN_VID_MASK;
+       vi->qos = vf_cfg->vlan_tag >> VLAN_PRIO_SHIFT;
+       memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN);
+@@ -1363,6 +1480,7 @@ static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
+       return 0;
+ }
++#ifdef HAVE_SET_VF_RATE
+ static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
+                            int min_tx_rate, int max_tx_rate)
+ {
+@@ -1425,6 +1543,8 @@ err:
+       return be_cmd_status(status);
+ }
++#endif
++
+ static int be_set_vf_link_state(struct net_device *netdev, int vf,
+                               int link_state)
+ {
+@@ -1460,7 +1580,7 @@ static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
+ static void be_eqd_update(struct be_adapter *adapter)
+ {
+       struct be_set_eqd set_eqd[MAX_EVT_QS];
+-      int eqd, i, num = 0, start;
++      int eqd, i, num = 0;
+       struct be_aic_obj *aic;
+       struct be_eq_obj *eqo;
+       struct be_rx_obj *rxo;
+@@ -1468,6 +1588,10 @@ static void be_eqd_update(struct be_adapter *adapter)
+       u64 rx_pkts, tx_pkts;
+       ulong now;
+       u32 pps, delta;
++      bool ret = false;
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++      int start;
++#endif
+       for_all_evt_queues(adapter, eqo, i) {
+               aic = &adapter->aic_obj[eqo->idx];
+@@ -1480,15 +1604,26 @@ static void be_eqd_update(struct be_adapter *adapter)
+               rxo = &adapter->rx_obj[eqo->idx];
+               do {
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
+                       start = u64_stats_fetch_begin_irq(&rxo->stats.sync);
++#endif
+                       rx_pkts = rxo->stats.rx_pkts;
+-              } while (u64_stats_fetch_retry_irq(&rxo->stats.sync, start));
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = u64_stats_fetch_retry_irq(&rxo->stats.sync, start);
++#endif
++              } while (ret);
+               txo = &adapter->tx_obj[eqo->idx];
+               do {
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = false;
+                       start = u64_stats_fetch_begin_irq(&txo->stats.sync);
++#endif
+                       tx_pkts = txo->stats.tx_reqs;
+-              } while (u64_stats_fetch_retry_irq(&txo->stats.sync, start));
++#ifdef HAVE_U64_STATS_FETCH_BEGIN_IRQ
++                      ret = u64_stats_fetch_retry_irq(&txo->stats.sync, start);
++#endif
++              } while (ret);
+               /* Skip, if wrapped around or first calculation */
+               now = jiffies;
+@@ -1685,18 +1820,28 @@ static void be_rx_compl_process(struct be_rx_obj *rxo, struct napi_struct *napi,
+       else
+               skb_checksum_none_assert(skb);
++#ifndef NULL_VLAN_GRP_SAFE
++      if (rxcp->vlanf && !adapter->vlan_grp) {
++              __vlan_put_tag(skb, rxcp->vlan_tag);
++              rxcp->vlanf = 0;
++      }
++#endif
+       skb->protocol = eth_type_trans(skb, netdev);
+       skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
+       if (netdev->features & NETIF_F_RXHASH)
+               skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3);
++#ifdef HAVE_SK_BUFF_CSUM_LEVEL
+       skb->csum_level = rxcp->tunneled;
++#else
++      skb->encapsulation = rxcp->tunneled;
++#endif
+       skb_mark_napi_id(skb, napi);
+       if (rxcp->vlanf)
+-              __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rxcp->vlan_tag);
+-
+-      netif_receive_skb(skb);
++              vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, rxcp->vlan_tag);
++      else
++              netif_receive_skb(skb);
+ }
+ /* Process the RX completion indicated by rxcp when GRO is enabled */
+@@ -1748,13 +1893,19 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo,
+       if (adapter->netdev->features & NETIF_F_RXHASH)
+               skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3);
++#ifdef HAVE_SK_BUFF_CSUM_LEVEL
+       skb->csum_level = rxcp->tunneled;
++#else
++      skb->encapsulation = rxcp->tunneled;
++#endif
++
+       skb_mark_napi_id(skb, napi);
+       if (rxcp->vlanf)
+-              __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rxcp->vlan_tag);
+-      napi_gro_frags(napi);
++              vlan_gro_frags(napi, adapter->vlan_grp, rxcp->vlan_tag);
++      else
++              napi_gro_frags(napi);
+ }
+ static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl,
+@@ -1983,7 +2134,11 @@ static u16 be_tx_compl_process(struct be_adapter *adapter,
+               queue_tail_inc(txq);
+       } while (cur_index != last_index);
++#ifdef HAVE_DEV_CONSUME_SKB_ANY
+       dev_consume_skb_any(sent_skb);
++#else
++      dev_kfree_skb_any(sent_skb);
++#endif
+       return num_wrbs;
+ }
+@@ -2253,9 +2408,10 @@ static int be_tx_qs_create(struct be_adapter *adapter)
+                                       sizeof(struct be_eth_tx_compl));
+               if (status)
+                       return status;
+-
++#ifdef HAVE_U64_STATS_SYNC
+               u64_stats_init(&txo->stats.sync);
+               u64_stats_init(&txo->stats.sync_compl);
++#endif
+               /* If num_evt_qs is less than num_tx_qs, then more than
+                * one txq share an eq
+@@ -2318,7 +2474,9 @@ static int be_rx_cqs_create(struct be_adapter *adapter)
+               if (rc)
+                       return rc;
++#ifdef HAVE_U64_STATS_SYNC
+               u64_stats_init(&rxo->stats.sync);
++#endif
+               eq = &adapter->eq_obj[i % adapter->num_evt_qs].q;
+               rc = be_cmd_cq_create(adapter, cq, eq, false, 3);
+               if (rc)
+@@ -2372,9 +2530,16 @@ static irqreturn_t be_msix(int irq, void *dev)
+       return IRQ_HANDLED;
+ }
+-static inline bool do_gro(struct be_rx_compl_info *rxcp)
++static inline bool do_gro(struct be_adapter *adapter,
++                        struct be_rx_compl_info *rxcp)
+ {
+-      return (rxcp->tcpf && !rxcp->err && rxcp->l4_csum) ? true : false;
++      bool insert_tag = false;
++
++#ifndef NULL_VLAN_GRP_SAFE
++      insert_tag = rxcp->vlanf && !adapter->vlan_grp;
++#endif
++      return rxcp->tcpf && !rxcp->err &&
++              rxcp->l4_csum && !insert_tag;
+ }
+ static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi,
+@@ -2411,7 +2576,7 @@ static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi,
+               }
+               /* Don't do gro when we're busy_polling */
+-              if (do_gro(rxcp) && polling != BUSY_POLLING)
++              if (do_gro(adapter, rxcp) && polling != BUSY_POLLING)
+                       be_rx_compl_process_gro(rxo, napi, rxcp);
+               else
+                       be_rx_compl_process(rxo, napi, rxcp);
+@@ -2664,6 +2829,9 @@ static int be_msix_enable(struct be_adapter *adapter)
+ {
+       int i, num_vec;
+       struct device *dev = &adapter->pdev->dev;
++#ifndef HAVE_PCI_ENABLE_MSIX_RANGE
++      int status;
++#endif
+       /* If RoCE is supported, program the max number of NIC vectors that
+        * may be configured via set-channels, along with vectors needed for
+@@ -2678,11 +2846,29 @@ static int be_msix_enable(struct be_adapter *adapter)
+       for (i = 0; i < num_vec; i++)
+               adapter->msix_entries[i].entry = i;
++#ifdef HAVE_PCI_ENABLE_MSIX_RANGE
+       num_vec = pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+                                       MIN_MSIX_VECTORS, num_vec);
+       if (num_vec < 0)
+               goto fail;
++#else
++      status = pci_enable_msix(adapter->pdev, adapter->msix_entries, num_vec);
++       if (status == 0) {
++              goto done;
++       } else if (status >= MIN_MSIX_VECTORS) {
++              dev_info(dev, "Could not get %d MSI-x vector(s)\n", num_vec);
++              dev_info(dev, "Using %d vector(s)\n", status);
++              num_vec = status;
++              status = pci_enable_msix(adapter->pdev, adapter->msix_entries,
++                                       num_vec);
++              if (status)
++                      goto fail;
++       } else {
++               goto fail;
++       }
++#endif
++done:
+       if (be_roce_supported(adapter) && num_vec > MIN_MSIX_VECTORS) {
+               adapter->num_msix_roce_vec = num_vec / 2;
+               dev_info(dev, "enabled %d MSI-x vector(s) for RoCE\n",
+@@ -2700,7 +2886,7 @@ fail:
+       /* INTx is not supported in VFs, so fail probe if enable_msix fails */
+       if (!be_physfn(adapter))
+-              return num_vec;
++              return status;
+       return 0;
+ }
+@@ -2977,7 +3163,7 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
+       cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
+       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+-                                   GFP_KERNEL);
++                                   GFP_KERNEL | __GFP_ZERO);
+       if (!cmd.va)
+               return -ENOMEM;
+@@ -3585,7 +3771,11 @@ static int be_setup_queues(struct be_adapter *adapter)
+       if (status)
+               goto err;
++#if HAVE_RETURN_INT_FOR_SET_NUM_TX_QUEUES
+       status = netif_set_real_num_tx_queues(netdev, adapter->num_tx_qs);
++#else
++      netif_set_real_num_tx_queues(netdev, adapter->num_tx_qs);
++#endif
+       if (status)
+               goto err;
+@@ -4297,6 +4487,16 @@ fw_exit:
+       return status;
+ }
++#ifndef USE_NEW_VLAN_MODEL
++static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
++{
++      struct be_adapter *adapter = netdev_priv(netdev);
++
++      adapter->vlan_grp = grp;
++}
++#endif
++
++#ifdef HAVE_NDO_BRIDGE_SET_GET_LINK
+ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh)
+ {
+       struct be_adapter *adapter = netdev_priv(dev);
+@@ -4363,6 +4563,8 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+                                      BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB);
+ }
++#endif
++
+ #ifdef CONFIG_BE2NET_VXLAN
+ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
+                             __be16 port)
+@@ -4421,11 +4623,6 @@ static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
+                "Disabled VxLAN offloads for UDP port %d\n",
+                be16_to_cpu(port));
+ }
+-
+-static bool be_gso_check(struct sk_buff *skb, struct net_device *dev)
+-{
+-      return vxlan_gso_check(skb);
+-}
+ #endif
+ static const struct net_device_ops be_netdev_ops = {
+@@ -4435,27 +4632,37 @@ static const struct net_device_ops be_netdev_ops = {
+       .ndo_set_rx_mode        = be_set_rx_mode,
+       .ndo_set_mac_address    = be_mac_addr_set,
+       .ndo_change_mtu         = be_change_mtu,
++#ifndef HAVE_NDO_GET_STATS64
++      .ndo_get_stats          = be_get_stats,
++#else
+       .ndo_get_stats64        = be_get_stats64,
++#endif
+       .ndo_validate_addr      = eth_validate_addr,
++#ifndef USE_NEW_VLAN_MODEL
++      .ndo_vlan_rx_register   = be_vlan_register,
++#endif
+       .ndo_vlan_rx_add_vid    = be_vlan_add_vid,
+       .ndo_vlan_rx_kill_vid   = be_vlan_rem_vid,
+       .ndo_set_vf_mac         = be_set_vf_mac,
+       .ndo_set_vf_vlan        = be_set_vf_vlan,
++#ifdef HAVE_SET_VF_RATE
+       .ndo_set_vf_rate        = be_set_vf_tx_rate,
++#endif
+       .ndo_get_vf_config      = be_get_vf_config,
+       .ndo_set_vf_link_state  = be_set_vf_link_state,
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = be_netpoll,
+ #endif
++#ifdef HAVE_NDO_BRIDGE_SET_GET_LINK
+       .ndo_bridge_setlink     = be_ndo_bridge_setlink,
+       .ndo_bridge_getlink     = be_ndo_bridge_getlink,
++#endif
+ #ifdef CONFIG_NET_RX_BUSY_POLL
+       .ndo_busy_poll          = be_busy_poll,
+ #endif
+ #ifdef CONFIG_BE2NET_VXLAN
+       .ndo_add_vxlan_port     = be_add_vxlan_port,
+       .ndo_del_vxlan_port     = be_del_vxlan_port,
+-      .ndo_gso_check          = be_gso_check,
+ #endif
+ };
+@@ -4481,7 +4688,9 @@ static void be_netdev_init(struct net_device *netdev)
+       netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
+               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
++#ifdef HAVE_NET_DEVICE_PRIV_FLAGS
+       netdev->priv_flags |= IFF_UNICAST_FLT;
++#endif
+       netdev->flags |= IFF_MULTICAST;
+@@ -4594,7 +4803,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
+       rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
+       rx_filter->va = dma_zalloc_coherent(&adapter->pdev->dev,
+                                           rx_filter->size, &rx_filter->dma,
+-                                          GFP_KERNEL);
++                                          GFP_KERNEL | __GFP_ZERO);
+       if (!rx_filter->va) {
+               status = -ENOMEM;
+               goto free_mbox;
+@@ -4643,7 +4852,7 @@ static int be_stats_init(struct be_adapter *adapter)
+               cmd->size = sizeof(struct be_cmd_req_get_stats_v2);
+       cmd->va = dma_zalloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
+-                                    GFP_KERNEL);
++                                    GFP_KERNEL | __GFP_ZERO);
+       if (!cmd->va)
+               return -ENOMEM;
+       return 0;
+-- 
+1.7.9.5
+