--- /dev/null
+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
+