From aa35e1f9be102a1f8c2649697b4541bca6512cb2 Mon Sep 17 00:00:00 2001 From: Selvin Xavier Date: Tue, 22 Aug 2017 14:11:23 -0700 Subject: [PATCH] bnxt_re: Add bnxt_re backports Signed-off-by: Selvin Xavier --- ...5-BACKPORT-bnxt_re-bnxt_re-backports.patch | 725 ++++++++++++++++++ 1 file changed, 725 insertions(+) create mode 100644 patches/0015-BACKPORT-bnxt_re-bnxt_re-backports.patch diff --git a/patches/0015-BACKPORT-bnxt_re-bnxt_re-backports.patch b/patches/0015-BACKPORT-bnxt_re-bnxt_re-backports.patch new file mode 100644 index 0000000..9732ce7 --- /dev/null +++ b/patches/0015-BACKPORT-bnxt_re-bnxt_re-backports.patch @@ -0,0 +1,725 @@ +From 669e648a47126dd70437ac974996f914153d37b1 Mon Sep 17 00:00:00 2001 +From: Selvin Xavier +Date: Tue, 22 Aug 2017 13:55:02 -0700 +Subject: [PATCH] BACKPORT-bnxt_re: bnxt_re backports + +Signed-off-by: Selvin Xavier +--- + 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 + -- 2.41.0