--- /dev/null
+From 669e648a47126dd70437ac974996f914153d37b1 Mon Sep 17 00:00:00 2001
+From: Selvin Xavier <selvin.xavier@broadcom.com>
+Date: Tue, 22 Aug 2017 13:55:02 -0700
+Subject: [PATCH] BACKPORT-bnxt_re: bnxt_re backports
+
+Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
+---
+ drivers/infiniband/hw/bnxt_re/ib_verbs.c | 15 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 214 ++++++++++++++----
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 259 ++++++++++++++++++++--
+ drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c | 6 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h | 2 +-
+ 5 files changed, 428 insertions(+), 68 deletions(-)
+
+diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+index d93a05f..cc53e6d 100644
+--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+@@ -225,16 +225,25 @@ int bnxt_re_modify_device(struct ib_device *ibdev,
+
+ static void __to_ib_speed_width(struct net_device *netdev, u8 *speed, u8 *width)
+ {
+- struct ethtool_link_ksettings lksettings;
+ u32 espeed;
+-
++#ifdef HAVE___ETHTOOL_GET_LINK_KSETTINGS
++ struct ethtool_link_ksettings lksettings;
+ if (netdev->ethtool_ops && netdev->ethtool_ops->get_link_ksettings) {
+ memset(&lksettings, 0, sizeof(lksettings));
+ rtnl_lock();
+ netdev->ethtool_ops->get_link_ksettings(netdev, &lksettings);
+ rtnl_unlock();
+ espeed = lksettings.base.speed;
+- } else {
++ }
++#else
++ struct ethtool_cmd ecmd;
++ if (netdev->ethtool_ops && netdev->ethtool_ops->get_settings) {
++ memset(&ecmd, 0, sizeof(ecmd));
++ netdev->ethtool_ops->get_settings(netdev, &ecmd);
++ espeed = ecmd.speed;
++ }
++#endif
++ else {
+ espeed = SPEED_UNKNOWN;
+ }
+ switch (espeed) {
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index d913237..f18d0cc 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3311,17 +3311,54 @@ static int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp,
+ req.ethertype = htons(ETH_P_IP);
+ memcpy(req.src_macaddr, fltr->src_mac_addr, ETH_ALEN);
+ req.ip_addr_type = CFA_NTUPLE_FILTER_ALLOC_REQ_IP_ADDR_TYPE_IPV4;
+- req.ip_protocol = keys->basic.ip_proto;
++#ifdef HAVE_SKB_FLOW_DISSECT_FLOW_KEYS
++ req.ip_protocol = keys->basic.ip_proto;
++
++ if (keys->basic.n_proto == htons(ETH_P_IPV6)) {
++ int i;
++
++ req.ethertype = htons(ETH_P_IPV6);
++ req.ip_addr_type =
++ CFA_NTUPLE_FILTER_ALLOC_REQ_IP_ADDR_TYPE_IPV6;
++ *(struct in6_addr *)&req.src_ipaddr[0] =
++ keys->addrs.v6addrs.src;
++ *(struct in6_addr *)&req.dst_ipaddr[0] =
++ keys->addrs.v6addrs.dst;
++ for (i = 0; i < 4; i++) {
++ req.src_ipaddr_mask[i] = cpu_to_be32(0xffffffff);
++ req.dst_ipaddr_mask[i] = cpu_to_be32(0xffffffff);
++ }
++ } else {
++ req.src_ipaddr[0] = keys->addrs.v4addrs.src;
++ req.src_ipaddr_mask[0] = cpu_to_be32(0xffffffff);
++ req.dst_ipaddr[0] = keys->addrs.v4addrs.dst;
++ req.dst_ipaddr_mask[0] = cpu_to_be32(0xffffffff);
++ }
++#ifdef HAVE_NEW_FLOW_DISSECTOR
++ if (keys->control.flags & FLOW_DIS_ENCAPSULATION) {
++ req.enables |= cpu_to_le32(BNXT_NTP_TUNNEL_FLTR_FLAG);
++ req.tunnel_type =
++ CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL;
++ }
++#endif
++
++ req.src_port = keys->ports.src;
++ req.src_port_mask = cpu_to_be16(0xffff);
++ req.dst_port = keys->ports.dst;
++ req.dst_port_mask = cpu_to_be16(0xffff);
++#else
++ req.ip_protocol = keys->ip_proto;
+
+- req.src_ipaddr[0] = keys->addrs.v4addrs.src;
+- req.src_ipaddr_mask[0] = cpu_to_be32(0xffffffff);
+- req.dst_ipaddr[0] = keys->addrs.v4addrs.dst;
+- req.dst_ipaddr_mask[0] = cpu_to_be32(0xffffffff);
++ req.src_ipaddr[0] = keys->src;
++ req.src_ipaddr_mask[0] = 0xffffffff;
++ req.dst_ipaddr[0] = keys->dst;
++ req.dst_ipaddr_mask[0] = 0xffffffff;
+
+- req.src_port = keys->ports.src;
+- req.src_port_mask = cpu_to_be16(0xffff);
+- req.dst_port = keys->ports.dst;
+- req.dst_port_mask = cpu_to_be16(0xffff);
++ req.src_port = keys->port16[0];
++ req.src_port_mask = 0xffff;
++ req.dst_port = keys->port16[1];
++ req.dst_port_mask = 0xffff;
++#endif
+
+ req.dst_id = cpu_to_le16(vnic->fw_vnic_id);
+ mutex_lock(&bp->hwrm_cmd_lock);
+@@ -5661,8 +5698,10 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
+ netdev_warn(bp->dev, "failed to update phy settings\n");
+ }
+
++#ifdef HAVE_UDP_TUNNEL_GET_RX_INFO
+ if (irq_re_init)
+ udp_tunnel_get_rx_info(bp->dev);
++#endif
+
+ set_bit(BNXT_STATE_OPEN, &bp->state);
+ bnxt_enable_int(bp);
+@@ -6508,34 +6547,68 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
+ return 0;
+ }
+
++#ifdef HAVE_NDO_SETUP_TC
++#ifdef HAVE_NDO_SETUP_TC_4_PARAMS
+ static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+ struct tc_to_netdev *ntc)
++#else
++static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
++ struct tc_to_netdev *ntc)
++#endif
+ {
+ if (ntc->type != TC_SETUP_MQPRIO)
+ return -EINVAL;
+
+ return bnxt_setup_mq_tc(dev, ntc->tc);
+ }
++#endif
+
+ #ifdef CONFIG_RFS_ACCEL
++#ifdef HAVE_SKB_FLOW_DISSECT_FLOW_KEYS
+ static bool bnxt_fltr_match(struct bnxt_ntuple_filter *f1,
+- struct bnxt_ntuple_filter *f2)
+-{
+- struct flow_keys *keys1 = &f1->fkeys;
+- struct flow_keys *keys2 = &f2->fkeys;
+-
+- if (keys1->addrs.v4addrs.src == keys2->addrs.v4addrs.src &&
+- keys1->addrs.v4addrs.dst == keys2->addrs.v4addrs.dst &&
+- keys1->ports.ports == keys2->ports.ports &&
+- keys1->basic.ip_proto == keys2->basic.ip_proto &&
+- keys1->basic.n_proto == keys2->basic.n_proto &&
+- ether_addr_equal(f1->src_mac_addr, f2->src_mac_addr) &&
+- ether_addr_equal(f1->dst_mac_addr, f2->dst_mac_addr))
+- return true;
++ struct bnxt_ntuple_filter *f2)
++{
++ struct flow_keys *keys1 = &f1->fkeys;
++ struct flow_keys *keys2 = &f2->fkeys;
++
++ if (keys1->addrs.v4addrs.src == keys2->addrs.v4addrs.src &&
++ keys1->addrs.v4addrs.dst == keys2->addrs.v4addrs.dst &&
++ keys1->ports.ports == keys2->ports.ports &&
++ keys1->basic.ip_proto == keys2->basic.ip_proto &&
++ keys1->basic.n_proto == keys2->basic.n_proto &&
++#ifdef HAVE_NEW_FLOW_DISSECTOR
++ keys1->control.flags == keys2->control.flags &&
++#endif
++ ether_addr_equal(f1->src_mac_addr, f2->src_mac_addr) &&
++ ether_addr_equal(f1->dst_mac_addr, f2->dst_mac_addr))
++ return true;
+
+- return false;
++ return false;
+ }
+
++#else
++
++static bool bnxt_fltr_match(struct bnxt_ntuple_filter *f1,
++ struct bnxt_ntuple_filter *f2)
++{
++ struct flow_keys *keys1 = &f1->fkeys;
++ struct flow_keys *keys2 = &f2->fkeys;
++
++ if (keys1->src == keys2->src &&
++ keys1->dst == keys2->dst &&
++ keys1->ports == keys2->ports &&
++ keys1->ip_proto == keys2->ip_proto &&
++#ifdef HAVE_N_PROTO
++ keys1->n_proto == keys2->n_proto &&
++#endif
++ ether_addr_equal(f1->src_mac_addr, f2->src_mac_addr) &&
++ ether_addr_equal(f1->dst_mac_addr, f2->dst_mac_addr))
++ return true;
++
++ return false;
++}
++#endif /* HAVE_SKB_FLOW_DISSECT_FLOW_KEYS*/
++
+ static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+ u16 rxq_index, u32 flow_id)
+ {
+@@ -6570,17 +6643,54 @@ static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+ return -ENOMEM;
+
+ fkeys = &new_fltr->fkeys;
+- if (!skb_flow_dissect_flow_keys(skb, fkeys, 0)) {
+- rc = -EPROTONOSUPPORT;
+- goto err_free;
+- }
++#ifdef HAVE_SKB_FLOW_DISSECT_FLOW_KEYS
++ if (!skb_flow_dissect_flow_keys(skb, fkeys, 0)) {
++ rc = -EPROTONOSUPPORT;
++ goto err_free;
++ }
++
++ if ((fkeys->basic.n_proto != htons(ETH_P_IP) &&
++ fkeys->basic.n_proto != htons(ETH_P_IPV6)) ||
++ ((fkeys->basic.ip_proto != IPPROTO_TCP) &&
++ (fkeys->basic.ip_proto != IPPROTO_UDP))) {
++ rc = -EPROTONOSUPPORT;
++ goto err_free;
++ }
++ if (fkeys->basic.n_proto == htons(ETH_P_IPV6) &&
++ bp->hwrm_spec_code < 0x10601) {
++ rc = -EPROTONOSUPPORT;
++ goto err_free;
++ }
++#ifdef HAVE_NEW_FLOW_DISSECTOR
++ if ((fkeys->control.flags & FLOW_DIS_ENCAPSULATION) &&
++ bp->hwrm_spec_code < 0x10601) {
++ rc = -EPROTONOSUPPORT;
++ goto err_free;
++ }
++#endif
++#else
++ if (!skb_flow_dissect(skb, fkeys)) {
++ rc = -EPROTONOSUPPORT;
++ goto err_free;
++ }
++
++#ifdef HAVE_N_PROTO
++ if ((fkeys->n_proto != htons(ETH_P_IP)) ||
++ ((fkeys->ip_proto != IPPROTO_TCP) &&
++ (fkeys->ip_proto != IPPROTO_UDP))) {
++ rc = -EPROTONOSUPPORT;
++ goto err_free;
++ }
++#else
++ if ((skb->protocol != htons(ETH_P_IP)) ||
++ ((fkeys->ip_proto != IPPROTO_TCP) &&
++ (fkeys->ip_proto != IPPROTO_UDP))) {
++ rc = -EPROTONOSUPPORT;
++ goto err_free;
++ }
++#endif
++#endif
+
+- if ((fkeys->basic.n_proto != htons(ETH_P_IP)) ||
+- ((fkeys->basic.ip_proto != IPPROTO_TCP) &&
+- (fkeys->basic.ip_proto != IPPROTO_UDP))) {
+- rc = -EPROTONOSUPPORT;
+- goto err_free;
+- }
+
+ memcpy(new_fltr->dst_mac_addr, eth->h_dest, ETH_ALEN);
+ memcpy(new_fltr->src_mac_addr, eth->h_source, ETH_ALEN);
+@@ -6678,6 +6788,7 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp)
+
+ #endif /* CONFIG_RFS_ACCEL */
+
++#ifdef HAVE_UDP_TUNNEL_GET_RX_INFO
+ static void bnxt_udp_tunnel_add(struct net_device *dev,
+ struct udp_tunnel_info *ti)
+ {
+@@ -6756,6 +6867,7 @@ static void bnxt_udp_tunnel_del(struct net_device *dev,
+
+ schedule_work(&bp->sp_task);
+ }
++#endif
+
+ static const struct net_device_ops bnxt_netdev_ops = {
+ .ndo_open = bnxt_open,
+@@ -6781,12 +6893,21 @@ static const struct net_device_ops bnxt_netdev_ops = {
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = bnxt_poll_controller,
+ #endif
++#ifdef HAVE_NDO_SETUP_TC
++#ifdef HAVE_NDO_SETUP_TC_4_PARAMS
+ .ndo_setup_tc = bnxt_setup_tc,
++#else
++ .ndo_setup_tc = bnxt_setup_mq_tc,
++#endif
++#endif
+ #ifdef CONFIG_RFS_ACCEL
+ .ndo_rx_flow_steer = bnxt_rx_flow_steer,
+ #endif
++#ifdef HAVE_UDP_TUNNEL_GET_RX_INFO
+ .ndo_udp_tunnel_add = bnxt_udp_tunnel_add,
+ .ndo_udp_tunnel_del = bnxt_udp_tunnel_del,
++#endif
++
+ #ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = bnxt_busy_poll,
+ #endif
+@@ -7052,9 +7173,14 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
+ NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
++#if 0
+ NETIF_F_GSO_IPXIP4 |
+- NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
+- NETIF_F_GSO_PARTIAL | NETIF_F_RXHASH |
++#endif
++ NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM
++#ifdef HAVE_NET_DEVICE_GSO_PARTIAL_FEATURES
++ | NETIF_F_GSO_PARTIAL
++#endif
++ | NETIF_F_RXHASH |
+ NETIF_F_RXCSUM | NETIF_F_GRO;
+
+ if (!BNXT_CHIP_TYPE_NITRO_A0(bp))
+@@ -7064,10 +7190,20 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
+ NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
+- NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
+- NETIF_F_GSO_IPXIP4 | NETIF_F_GSO_PARTIAL;
++ NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM
++#if 0
++ | NETIF_F_GSO_IPXIP4
++#endif
++#ifdef HAVE_NET_DEVICE_GSO_PARTIAL_FEATURES
++ | NETIF_F_GSO_PARTIAL
++#endif
++ ;
++
++
++#ifdef HAVE_NET_DEVICE_GSO_PARTIAL_FEATURES
+ dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_GSO_GRE_CSUM;
++#endif
+ dev->vlan_features = dev->hw_features | NETIF_F_HIGHDMA;
+ dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX;
+@@ -7075,8 +7211,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ dev->priv_flags |= IFF_UNICAST_FLT;
+
+ /* MTU range: 60 - 9500 */
+- dev->min_mtu = ETH_ZLEN;
+- dev->max_mtu = 9500;
++ //dev->min_mtu = ETH_ZLEN;
++ //dev->max_mtu = 9500;
+
+ bnxt_dcb_init(bp);
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+index 784aa77..198caa5 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+@@ -524,27 +524,50 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
+
+ fltr_found:
+ fkeys = &fltr->fkeys;
+- if (fkeys->basic.ip_proto == IPPROTO_TCP)
+- fs->flow_type = TCP_V4_FLOW;
+- else if (fkeys->basic.ip_proto == IPPROTO_UDP)
+- fs->flow_type = UDP_V4_FLOW;
+- else
+- goto fltr_err;
+-
+- fs->h_u.tcp_ip4_spec.ip4src = fkeys->addrs.v4addrs.src;
+- fs->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(~0);
+-
+- fs->h_u.tcp_ip4_spec.ip4dst = fkeys->addrs.v4addrs.dst;
+- fs->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(~0);
+
+- fs->h_u.tcp_ip4_spec.psrc = fkeys->ports.src;
+- fs->m_u.tcp_ip4_spec.psrc = cpu_to_be16(~0);
++#ifdef NEW_FLOW_KEYS
++ if (fkeys->basic.n_proto == htons(ETH_P_IP)) {
++ if (fkeys->basic.ip_proto == IPPROTO_TCP)
++ fs->flow_type = TCP_V4_FLOW;
++ else if (fkeys->basic.ip_proto == IPPROTO_UDP)
++ fs->flow_type = UDP_V4_FLOW;
++ else
++ goto fltr_err;
++
++ fs->h_u.tcp_ip4_spec.ip4src = fkeys->addrs.v4addrs.src;
++ fs->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(~0);
++
++ fs->h_u.tcp_ip4_spec.ip4dst = fkeys->addrs.v4addrs.dst;
++ fs->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(~0);
++
++ fs->h_u.tcp_ip4_spec.psrc = fkeys->ports.src;
++ fs->m_u.tcp_ip4_spec.psrc = cpu_to_be16(~0);
++
++ fs->h_u.tcp_ip4_spec.pdst = fkeys->ports.dst;
++ fs->m_u.tcp_ip4_spec.pdst = cpu_to_be16(~0);
++ }
++#else
++ if (fkeys->ip_proto == IPPROTO_TCP)
++ fs->flow_type = TCP_V4_FLOW;
++ else if (fkeys->ip_proto == IPPROTO_UDP)
++ fs->flow_type = UDP_V4_FLOW;
++ else
++ goto fltr_err;
++
++ fs->h_u.tcp_ip4_spec.ip4src = fkeys->src;
++ fs->m_u.tcp_ip4_spec.ip4src = (__be32) ~0;
++
++ fs->h_u.tcp_ip4_spec.ip4dst = fkeys->dst;
++ fs->m_u.tcp_ip4_spec.ip4dst = (__be32) ~0;
++
++ fs->h_u.tcp_ip4_spec.psrc = fkeys->port16[0];
++ fs->m_u.tcp_ip4_spec.psrc = (__be16) ~0;
++
++ fs->h_u.tcp_ip4_spec.pdst = fkeys->port16[1];
++ fs->m_u.tcp_ip4_spec.pdst = (__be16) ~0;
++#endif
+
+- fs->h_u.tcp_ip4_spec.pdst = fkeys->ports.dst;
+- fs->m_u.tcp_ip4_spec.pdst = cpu_to_be16(~0);
+
+- fs->ring_cookie = fltr->rxq;
+- rc = 0;
+
+ fltr_err:
+ rcu_read_unlock();
+@@ -832,6 +855,7 @@ u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause)
+ return speed_mask;
+ }
+
++#ifdef HAVE_ETHTOOL_xLINKSETTINGS
+ #define BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, fw_pause, lk_ksettings, name)\
+ { \
+ if ((fw_speeds) & BNXT_LINK_SPEED_MSK_100MB) \
+@@ -930,6 +954,50 @@ static void bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info,
+ ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
+ Autoneg);
+ }
++#else
++
++static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info)
++{
++ u16 fw_speeds = link_info->advertising;
++ u8 fw_pause = 0;
++
++ if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
++ fw_pause = link_info->auto_pause_setting;
++
++ return _bnxt_fw_to_ethtool_adv_spds(fw_speeds, fw_pause);
++}
++
++static u32 bnxt_fw_to_ethtool_lp_adv(struct bnxt_link_info *link_info)
++{
++ u16 fw_speeds = link_info->lp_auto_link_speeds;
++ u8 fw_pause = 0;
++
++ if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
++ fw_pause = link_info->lp_pause;
++
++ return _bnxt_fw_to_ethtool_adv_spds(fw_speeds, fw_pause);
++}
++
++static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info)
++{
++ u16 fw_speeds = link_info->support_speeds;
++ u32 supported;
++
++ supported = _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0);
++ return supported | SUPPORTED_Pause | SUPPORTED_Asym_Pause;
++}
++
++static u32 bnxt_fw_to_ethtool_support_adv_spds(struct bnxt_link_info *link_info)
++{
++ u16 fw_speeds = link_info->support_auto_speeds;
++ u32 supported;
++
++ supported = _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0);
++ if (supported)
++ supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
++ return supported;
++}
++#endif
+
+ u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
+ {
+@@ -955,6 +1023,7 @@ u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
+ }
+ }
+
++#ifdef HAVE_ETHTOOL_xLINKSETTINGS
+ static int bnxt_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *lk_ksettings)
+ {
+@@ -1014,6 +1083,71 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
+
+ return 0;
+ }
++#else
++static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct bnxt *bp = netdev_priv(dev);
++ struct bnxt_link_info *link_info = &bp->link_info;
++ u32 ethtool_speed;
++
++ cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info);
++
++ if (link_info->support_auto_speeds)
++ cmd->supported |= SUPPORTED_Autoneg;
++
++ if (link_info->autoneg) {
++ cmd->advertising =
++ bnxt_fw_to_ethtool_advertised_spds(link_info);
++ cmd->advertising |= ADVERTISED_Autoneg;
++ cmd->autoneg = AUTONEG_ENABLE;
++ if (link_info->phy_link_status == BNXT_LINK_LINK)
++ cmd->lp_advertising =
++ bnxt_fw_to_ethtool_lp_adv(link_info);
++ ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed);
++ if (!netif_carrier_ok(dev))
++ cmd->duplex = DUPLEX_UNKNOWN;
++ else if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
++ cmd->duplex = DUPLEX_FULL;
++ else
++ cmd->duplex = DUPLEX_HALF;
++ } else {
++ cmd->autoneg = AUTONEG_DISABLE;
++ cmd->advertising = 0;
++ ethtool_speed =
++ bnxt_fw_to_ethtool_speed(link_info->req_link_speed);
++ cmd->duplex = DUPLEX_HALF;
++ if (link_info->req_duplex == BNXT_LINK_DUPLEX_FULL)
++ cmd->duplex = DUPLEX_FULL;
++ }
++ ethtool_cmd_speed_set(cmd, ethtool_speed);
++
++ cmd->port = PORT_NONE;
++ if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
++ cmd->port = PORT_TP;
++ cmd->supported |= SUPPORTED_TP;
++ cmd->advertising |= ADVERTISED_TP;
++ } else {
++ cmd->supported |= SUPPORTED_FIBRE;
++ cmd->advertising |= ADVERTISED_FIBRE;
++
++ if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC)
++ cmd->port = PORT_DA;
++ else if (link_info->media_type ==
++ PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE)
++ cmd->port = PORT_FIBRE;
++ }
++
++ if (link_info->transceiver ==
++ PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL)
++ cmd->transceiver = XCVR_INTERNAL;
++ else
++ cmd->transceiver = XCVR_EXTERNAL;
++ cmd->phy_address = link_info->phy_addr;
++
++ return 0;
++}
++
++#endif
+
+ static u32 bnxt_get_fw_speed(struct net_device *dev, u16 ethtool_speed)
+ {
+@@ -1084,6 +1218,7 @@ u16 bnxt_get_fw_auto_link_speeds(u32 advertising)
+ return fw_speed_mask;
+ }
+
++#ifdef HAVE_ETHTOOL_xLINKSETTINGS
+ static int bnxt_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *lk_ksettings)
+ {
+@@ -1143,6 +1278,85 @@ static int bnxt_set_link_ksettings(struct net_device *dev,
+ set_setting_exit:
+ return rc;
+ }
++#else
++static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ int rc = 0;
++ struct bnxt *bp = netdev_priv(dev);
++ struct bnxt_link_info *link_info = &bp->link_info;
++ bool set_pause = false;
++ u16 fw_advertising = 0;
++ u32 speed;
++
++ if (!BNXT_SINGLE_PF(bp))
++ return -EOPNOTSUPP;
++
++ if (cmd->autoneg == AUTONEG_ENABLE) {
++ u32 supported_spds =
++ bnxt_fw_to_ethtool_support_adv_spds(link_info);
++
++ if (!supported_spds) {
++ netdev_err(dev, "Autoneg not supported\n");
++ rc = -EINVAL;
++ goto set_setting_exit;
++ }
++ if (cmd->advertising & ~(supported_spds | ADVERTISED_Autoneg |
++ ADVERTISED_TP | ADVERTISED_FIBRE)) {
++ netdev_err(dev, "Unsupported advertising mask (adv: 0x%x)\n",
++ cmd->advertising);
++ rc = -EINVAL;
++ goto set_setting_exit;
++ }
++ fw_advertising = bnxt_get_fw_auto_link_speeds(cmd->advertising);
++ link_info->autoneg |= BNXT_AUTONEG_SPEED;
++ if (!fw_advertising)
++ link_info->advertising = link_info->support_auto_speeds;
++ else
++ link_info->advertising = fw_advertising;
++ /* any change to autoneg will cause link change, therefore the
++ * * driver should put back the original pause setting in autoneg
++ * */
++ set_pause = true;
++ } else {
++ u16 fw_speed;
++ u8 phy_type = link_info->phy_type;
++
++ if (phy_type == PORT_PHY_QCFG_RESP_PHY_TYPE_BASET ||
++ phy_type == PORT_PHY_QCFG_RESP_PHY_TYPE_BASETE ||
++ link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
++
++ netdev_err(dev, "10GBase-T devices must autoneg\n");
++ rc = -EINVAL;
++ goto set_setting_exit;
++ }
++ /* TODO: currently don't support half duplex */
++ if (cmd->duplex == DUPLEX_HALF) {
++ netdev_err(dev, "HALF DUPLEX is not supported!\n");
++ rc = -EINVAL;
++ goto set_setting_exit;
++ }
++ /* If received a request for an unknown duplex, assume full*/
++ if (cmd->duplex == DUPLEX_UNKNOWN)
++ cmd->duplex = DUPLEX_FULL;
++ speed = ethtool_cmd_speed(cmd);
++ fw_speed = bnxt_get_fw_speed(dev, speed);
++ if (!fw_speed) {
++ rc = -EINVAL;
++ goto set_setting_exit;
++ }
++ link_info->req_link_speed = fw_speed;
++ link_info->req_duplex = BNXT_LINK_DUPLEX_FULL;
++ link_info->autoneg = 0;
++ link_info->advertising = 0;
++ }
++
++ if (netif_running(dev))
++ rc = bnxt_hwrm_set_link_setting(bp, set_pause, false);
++
++set_setting_exit:
++ return rc;
++}
++#endif
+
+ static void bnxt_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *epause)
+@@ -2040,8 +2254,13 @@ static int bnxt_nway_reset(struct net_device *dev)
+ }
+
+ const struct ethtool_ops bnxt_ethtool_ops = {
+- .get_link_ksettings = bnxt_get_link_ksettings,
+- .set_link_ksettings = bnxt_set_link_ksettings,
++#ifdef HAVE_ETHTOOL_xLINKSETTINGS
++ .get_link_ksettings = bnxt_get_link_ksettings,
++ .set_link_ksettings = bnxt_set_link_ksettings,
++#else
++ .get_settings = bnxt_get_settings,
++ .set_settings = bnxt_set_settings,
++#endif
+ .get_pauseparam = bnxt_get_pauseparam,
+ .set_pauseparam = bnxt_set_pauseparam,
+ .get_drvinfo = bnxt_get_drvinfo,
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+index c696025..477e265 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+@@ -173,8 +173,7 @@ int bnxt_set_vf_mac(struct net_device *dev, int vf_id, u8 *mac)
+ return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+ }
+
+-int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos,
+- __be16 vlan_proto)
++int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos)
+ {
+ struct hwrm_func_cfg_input req = {0};
+ struct bnxt *bp = netdev_priv(dev);
+@@ -185,9 +184,6 @@ int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos,
+ if (bp->hwrm_spec_code < 0x10201)
+ return -ENOTSUPP;
+
+- if (vlan_proto != htons(ETH_P_8021Q))
+- return -EPROTONOSUPPORT;
+-
+ rc = bnxt_vf_ndo_prep(bp, vf_id);
+ if (rc)
+ return rc;
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h
+index 1ab72e4..0392670 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h
+@@ -12,7 +12,7 @@
+
+ int bnxt_get_vf_config(struct net_device *, int, struct ifla_vf_info *);
+ int bnxt_set_vf_mac(struct net_device *, int, u8 *);
+-int bnxt_set_vf_vlan(struct net_device *, int, u16, u8, __be16);
++int bnxt_set_vf_vlan(struct net_device *, int, u16, u8);
+ int bnxt_set_vf_bw(struct net_device *, int, int, int);
+ int bnxt_set_vf_link_state(struct net_device *, int, int);
+ int bnxt_set_vf_spoofchk(struct net_device *, int, bool);
+--
+2.5.5
+