diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile index bd5aea7dd4904faea75015f5b15a92fca8d44d8e..5f188d5c3d9dc4fe648e4c605f43c158ba577638 100644 --- a/drivers/net/ethernet/hisilicon/hns3/Makefile +++ b/drivers/net/ethernet/hisilicon/hns3/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_HNS3) += hnae3.o obj-$(CONFIG_HNS3_ENET) += hns3.o hns3-objs = hns3_enet.o hns3_ethtool.o hns3_debugfs.o -hns3-objs += hns3_ext.o +hns3-objs += hns3_ext.o hns3_roh.o hns3-$(CONFIG_HNS3_DCB) += hns3_dcbnl.o hns3-$(CONFIG_HNS3_UBL) += hns3_unic.o hns3_unic_debugfs.o diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 124ba9dca6b0b54e6bc57f20d40b8cc1a81cf05e..ec23633c49b2ef4fd5b789d9929cec870bdd56b6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -984,6 +984,7 @@ enum hnae3_pflag { HNAE3_PFLAG_LIMIT_PROMISC, HNAE3_PFLAG_PUSH_ENABLE, HNAE3_PFLAG_FD_QB_ENABLE, + HNAE3_PFLAG_ROH_ARP_PROXY_ENABLE, HNAE3_PFLAG_MAX }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 5cdfa8e06ddf5f1d725ef211801e8e32cef7772e..403a34a422bc7bb7c228e07db0d6bb8b2b9ef062 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -505,11 +505,14 @@ static void hns3_get_coal_info(struct hns3_enet_tqp_vector *tqp_vector, } sprintf(result[j++], "%d", i); - sprintf(result[j++], "%s", dim_state_str[dim->state]); + sprintf(result[j++], "%s", dim->state < ARRAY_SIZE(dim_state_str) ? + dim_state_str[dim->state] : "unknown"); sprintf(result[j++], "%u", dim->profile_ix); - sprintf(result[j++], "%s", dim_cqe_mode_str[dim->mode]); + sprintf(result[j++], "%s", dim->mode < ARRAY_SIZE(dim_cqe_mode_str) ? + dim_cqe_mode_str[dim->mode] : "unknown"); sprintf(result[j++], "%s", - dim_tune_stat_str[dim->tune_state]); + dim->tune_state < ARRAY_SIZE(dim_tune_stat_str) ? + dim_tune_stat_str[dim->tune_state] : "unknown"); sprintf(result[j++], "%u", dim->steps_left); sprintf(result[j++], "%u", dim->steps_right); sprintf(result[j++], "%u", dim->tired); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index abbfe7a4117fab6ba33da9e2233ef5b49fe3ec16..de2c2d8a9536e38e9ece63345b5e732bc0327006 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -28,6 +28,7 @@ #include "hnae3_ext.h" #include "hns3_enet.h" #include "hns3_unic.h" +#include "hns3_roh.h" /* All hns3 tracepoints are defined by the include below, which * must be included exactly once across the whole kernel with * CREATE_TRACE_POINTS defined @@ -2588,6 +2589,11 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) hns3_unic_set_default_cc(skb); } #endif + if (test_bit(HNAE3_PFLAG_ROH_ARP_PROXY_ENABLE, + &priv->ae_handle->priv_flags) && + hns3_need_to_handle_roh_arp_req(skb)) + return hns3_handle_roh_arp_req(skb, priv); + ret = hns3_handle_skb_desc(priv, ring, skb, desc_cb, ring->next_to_use); if (unlikely(ret <= 0)) goto out_err_tx_ok; @@ -4821,6 +4827,9 @@ static int hns3_nic_common_poll(struct napi_struct *napi, int budget) if (tqp_vector->num_tqps > 1) rx_budget = max(budget / tqp_vector->num_tqps, 1); + if (hnae3_check_roh_mac_type(priv->ae_handle)) + hns3_handle_roh_arp_reply(tqp_vector, priv); + hns3_for_each_ring(ring, tqp_vector->rx_group) { int rx_cleaned = hns3_clean_rx_ring(ring, rx_budget, hns3_rx_skb); @@ -5475,7 +5484,7 @@ static int hns3_init_mac_addr(struct net_device *netdev) struct hns3_nic_priv *priv = netdev_priv(netdev); char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN]; struct hnae3_handle *h = priv->ae_handle; - u8 mac_addr_temp[ETH_ALEN]; + u8 mac_addr_temp[ETH_ALEN] = {0}; int ret = 0; if (hns3_ubl_supported(h)) @@ -5621,6 +5630,12 @@ static void hns3_state_init(struct hnae3_handle *handle) if (hnae3_ae_dev_rxd_adv_layout_supported(ae_dev)) set_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state); + + if (hnae3_check_roh_mac_type(handle)) { + set_bit(HNAE3_PFLAG_ROH_ARP_PROXY_ENABLE, + &handle->supported_pflags); + set_bit(HNAE3_PFLAG_ROH_ARP_PROXY_ENABLE, &handle->priv_flags); + } } static void hns3_state_uninit(struct hnae3_handle *handle) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 498103e4884da4f0296e1de1a562ddb8151cd03d..c0237202feae7be7b48f018219113a7bd7918518 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -471,6 +471,15 @@ struct hns3_tx_spare { u32 len; }; +struct hns3_arp_reply { + __be32 dest_ip; + __be32 src_ip; + u8 dest_hw[ETH_ALEN]; + u8 src_hw[ETH_ALEN]; + u8 has_vlan; + __be16 vlan_tci; +}; + struct hns3_enet_ring { struct hns3_desc *desc; /* dma map address space */ struct hns3_desc_cb *desc_cb; @@ -496,6 +505,11 @@ struct hns3_enet_ring { int next_to_clean; u32 flag; /* ring attribute */ +#define HNS3_APR_REPLY_LTH 32 + struct hns3_arp_reply arp_reply[HNS3_APR_REPLY_LTH]; + int arp_reply_head; + int arp_reply_tail; + int pending_buf; union { /* for Tx ring */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index c0afdc1af05a791215231cc2fc55b39991f02b10..50661a3f6d3f26c3c7c86ddfc926a8052f36424a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -523,10 +523,18 @@ static void hns3_update_push_state(struct net_device *netdev, bool enable) hns3_update_state(netdev, HNS3_NIC_STATE_TX_PUSH_ENABLE, enable); } +static void hns3_update_roh_arp_proxy_enable(struct net_device *netdev, + bool enable) +{ + netdev_info(netdev, "%s roh arp proxy\n", + enable ? "enable" : "disable"); +} + static const struct hns3_pflag_desc hns3_priv_flags[HNAE3_PFLAG_MAX] = { { "limit_promisc", hns3_update_limit_promisc_mode }, { "tx_push_enable", hns3_update_push_state }, { "qb_enable", hns3_update_fd_qb_state }, + { "roh_arp_proxy_enable", hns3_update_roh_arp_proxy_enable }, }; static int hns3_get_sset_count(struct net_device *netdev, int stringset) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_roh.c b/drivers/net/ethernet/hisilicon/hns3/hns3_roh.c new file mode 100644 index 0000000000000000000000000000000000000000..b0fa565ba36f680ab1304a14772dfab42ec0e3c5 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_roh.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2016-2017 Hisilicon Limited. + +#include +#include +#include +#include + +#include "hns3_roh.h" +#include "hns3_enet.h" + +static void hns3_extract_arp_ip_field(struct arphdr *arphdr, __be32 **sip, + __be32 **tip, unsigned char addr_len) +{ + unsigned char *arp_ptr = (unsigned char *)(arphdr + 1); + + arp_ptr += addr_len; + *sip = (__be32 *)arp_ptr; + arp_ptr += ARP_IP_LEN; + arp_ptr += addr_len; + *tip = (__be32 *)arp_ptr; +} + +bool hns3_need_to_handle_roh_arp_req(struct sk_buff *skb) +{ + struct arphdr *arphdr = arp_hdr(skb); + __be32 *sip, *tip; + + /* Intercept most non-ARP packets based on packet length. */ + if (skb->len > hns3_roh_arp_hlen_max(skb)) + return false; + + /* if txvlan offload is off, check encapsulated protocol in vlan. */ + if (eth_type_vlan(skb->protocol)) { + struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data + ETH_HLEN); + + if (vh->h_vlan_encapsulated_proto == htons(ETH_P_ARP) && + arphdr->ar_op == htons(ARPOP_REQUEST)) + goto check_gratuitous_arp; + return false; + } + + /* if txvlan offload is on or it's a normal packet, check protocol. */ + if (skb->protocol != htons(ETH_P_ARP) || + arphdr->ar_op != htons(ARPOP_REQUEST)) + return false; + + /* don't support Gratuitous ARP, which request packet where the source + * and destination IP are both set to the IP of the machine issuing the + * packet. + */ +check_gratuitous_arp: + hns3_extract_arp_ip_field(arphdr, &sip, &tip, skb->dev->addr_len); + return *tip != *sip; +} + +int hns3_handle_roh_arp_req(struct sk_buff *skb, struct hns3_nic_priv *priv) +{ + struct hnae3_handle *h = priv->ae_handle; + struct hns3_enet_ring *ring; + struct arphdr *arphdr; + struct ethhdr *ethhdr; + int reply_idx, len; + __be32 *sip, *tip; + + /* use same queue num in rx */ + ring = &priv->ring[skb->queue_mapping + h->kinfo.num_tqps]; + reply_idx = ring->arp_reply_tail; + hns3_roh_arp_reply_idx_move_fd(reply_idx); + /* This smp_load_acquire() pairs with smp_store_release() in + * hns3_handle_roh_arp_reply(). + */ + if (reply_idx == smp_load_acquire(&ring->arp_reply_head)) + return NETDEV_TX_BUSY; + len = skb->len; + + if (skb_vlan_tagged(skb)) { + ring->arp_reply[reply_idx].has_vlan = true; + ring->arp_reply[reply_idx].vlan_tci = skb_vlan_tag_get(skb); + skb_vlan_pop(skb); + len += VLAN_HLEN; + } else { + ring->arp_reply[reply_idx].has_vlan = false; + } + + ethhdr = eth_hdr(skb); + arphdr = arp_hdr(skb); + + hns3_extract_arp_ip_field(arphdr, &sip, &tip, skb->dev->addr_len); + ether_addr_copy(ring->arp_reply[reply_idx].dest_hw, ethhdr->h_source); + ether_addr_copy(ring->arp_reply[reply_idx].src_hw, ethhdr->h_dest); + ring->arp_reply[reply_idx].dest_ip = *sip; + ring->arp_reply[reply_idx].src_ip = *tip; + hns3_roh_update_mac_by_ip(be32_to_cpu(*tip), + ring->arp_reply[reply_idx].src_hw); + /* This smp_store_release() pairs with smp_load_acquire() in + * hns3_handle_roh_arp_reply(). Ensure that the arp_reply_tail is + * update validly. + */ + smp_store_release(&ring->arp_reply_tail, reply_idx); + + ring = &priv->ring[skb->queue_mapping]; + u64_stats_update_begin(&ring->syncp); + ring->stats.tx_pkts++; + ring->stats.tx_bytes += len; + u64_stats_update_end(&ring->syncp); + + dev_kfree_skb_any(skb); + napi_schedule(&ring->tqp_vector->napi); + return NETDEV_TX_OK; +} + +static struct sk_buff *setup_arp_reply_skb(struct hns3_arp_reply *arp_reply, + struct hns3_nic_priv *priv) +{ + struct sk_buff *skb = arp_create(ARPOP_REPLY, ETH_P_ARP, + arp_reply->dest_ip, priv->netdev, + arp_reply->src_ip, arp_reply->dest_hw, + arp_reply->src_hw, arp_reply->dest_hw); + if (!skb) + return NULL; + + skb_reset_mac_header(skb); + skb_reset_mac_len(skb); + + if (arp_reply->has_vlan) { + skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q), + arp_reply->vlan_tci); + if (!skb) + return NULL; + skb_reset_network_header(skb); + } + + skb_reserve(skb, skb->mac_len); + return skb; +} + +void hns3_handle_roh_arp_reply(struct hns3_enet_tqp_vector *tqp_vector, + struct hns3_nic_priv *priv) +{ + struct hns3_arp_reply *arp_reply; + struct hns3_enet_ring *ring; + struct sk_buff *skb; + int reply_idx; + + hns3_for_each_ring(ring, tqp_vector->rx_group) { + /* This smp_load_acquire() pairs with smp_store_release() in + * hns3_handle_roh_arp_reply(). + */ + while (smp_load_acquire(&ring->arp_reply_tail) != + ring->arp_reply_head) { + reply_idx = ring->arp_reply_head; + hns3_roh_arp_reply_idx_move_fd(reply_idx); + arp_reply = &ring->arp_reply[reply_idx]; + skb = setup_arp_reply_skb(arp_reply, priv); + /* This smp_store_release() pairs with + * smp_load_acquire() in hns3_handle_roh_arp_req(). + * Ensure that the arp_reply_head is update validly. + */ + smp_store_release(&ring->arp_reply_head, reply_idx); + + if (!skb) { + hns3_ring_stats_update(ring, rx_err_cnt); + continue; + } + napi_gro_receive(&tqp_vector->napi, skb); + + u64_stats_update_begin(&ring->syncp); + ring->stats.rx_pkts++; + ring->stats.rx_bytes += skb->len; + u64_stats_update_end(&ring->syncp); + } + } +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_roh.h b/drivers/net/ethernet/hisilicon/hns3/hns3_roh.h new file mode 100644 index 0000000000000000000000000000000000000000..2ea8c6a29441a171dcabbda9483c9ab6a9f147f7 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_roh.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +// Copyright (c) 2023 Hisilicon Limited. + +#ifndef __HNS3_ROH_H +#define __HNS3_ROH_H + +#include "hns3_enet.h" + +#define ARP_IP_LEN 4 +#define HNS3_ROH_MAC_ADDR_MASK 0x00ffffff + +#define hns3_roh_update_mac_by_ip(ip_addr, mac) \ + u64_to_ether_addr((ip_addr) & HNS3_ROH_MAC_ADDR_MASK, mac) +#define hns3_roh_arp_hlen_max(skb) \ + (ETH_HLEN + arp_hdr_len((skb)->dev) + VLAN_HLEN) +#define hns3_roh_arp_reply_idx_move_fd(idx) \ + ({ typeof(idx) x_ = (idx); \ + x_ = (x_ + 1) % HNS3_APR_REPLY_LTH; }) + +void hns3_handle_roh_arp_reply(struct hns3_enet_tqp_vector *tqp_vector, + struct hns3_nic_priv *priv); +int hns3_handle_roh_arp_req(struct sk_buff *skb, struct hns3_nic_priv *priv); +bool hns3_need_to_handle_roh_arp_req(struct sk_buff *skb); +#endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 87fdc6a0931a8edff11c5e7a44e0df5d51002bd8..3b6278eafc0cb81a9cbc6f4e764e0bde1aba47b5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -70,6 +70,7 @@ static void hclge_sync_fd_table(struct hclge_dev *hdev); static void hclge_reset_end(struct hnae3_handle *handle, bool done); static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret, int wait_cnt); +static int hclge_update_port_info(struct hclge_dev *hdev); static struct hnae3_ae_algo ae_algo; @@ -946,8 +947,8 @@ static const struct hclge_speed_bit_map speed_bit_map[] = { {HCLGE_MAC_SPEED_10G, HCLGE_SUPPORT_10G_BIT}, {HCLGE_MAC_SPEED_25G, HCLGE_SUPPORT_25G_BIT}, {HCLGE_MAC_SPEED_40G, HCLGE_SUPPORT_40G_BIT}, - {HCLGE_MAC_SPEED_50G, HCLGE_SUPPORT_50G_BIT}, - {HCLGE_MAC_SPEED_100G, HCLGE_SUPPORT_100G_BIT}, + {HCLGE_MAC_SPEED_50G, HCLGE_SUPPORT_50G_BITS}, + {HCLGE_MAC_SPEED_100G, HCLGE_SUPPORT_100G_BITS}, {HCLGE_MAC_SPEED_200G, HCLGE_SUPPORT_200G_BIT}, }; @@ -1004,100 +1005,98 @@ static void hclge_update_fec_support(struct hclge_mac *mac) mac->supported); } +static const struct hclge_link_mode_bmap hclge_sr_link_mode_bmap[8] = { + {HCLGE_SUPPORT_10G_BIT, ETHTOOL_LINK_MODE_10000baseSR_Full_BIT}, + {HCLGE_SUPPORT_25G_BIT, ETHTOOL_LINK_MODE_25000baseSR_Full_BIT}, + {HCLGE_SUPPORT_40G_BIT, ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT}, + {HCLGE_SUPPORT_50G_R2_BIT, ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT}, + {HCLGE_SUPPORT_50G_R1_BIT, ETHTOOL_LINK_MODE_50000baseSR_Full_BIT}, + {HCLGE_SUPPORT_100G_R4_BIT, ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT}, + {HCLGE_SUPPORT_100G_R2_BIT, ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT}, + {HCLGE_SUPPORT_200G_BIT, ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT}, +}; + +static const struct hclge_link_mode_bmap hclge_lr_link_mode_bmap[6] = { + {HCLGE_SUPPORT_10G_BIT, ETHTOOL_LINK_MODE_10000baseLR_Full_BIT}, + {HCLGE_SUPPORT_40G_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT}, + {HCLGE_SUPPORT_50G_R1_BIT, ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT}, + {HCLGE_SUPPORT_100G_R4_BIT, + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT}, + {HCLGE_SUPPORT_100G_R2_BIT, + ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT}, + {HCLGE_SUPPORT_200G_BIT, + ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT}, +}; + +static const struct hclge_link_mode_bmap hclge_cr_link_mode_bmap[8] = { + {HCLGE_SUPPORT_10G_BIT, ETHTOOL_LINK_MODE_10000baseCR_Full_BIT}, + {HCLGE_SUPPORT_25G_BIT, ETHTOOL_LINK_MODE_25000baseCR_Full_BIT}, + {HCLGE_SUPPORT_40G_BIT, ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT}, + {HCLGE_SUPPORT_50G_R2_BIT, ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT}, + {HCLGE_SUPPORT_50G_R1_BIT, ETHTOOL_LINK_MODE_50000baseCR_Full_BIT}, + {HCLGE_SUPPORT_100G_R4_BIT, ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT}, + {HCLGE_SUPPORT_100G_R2_BIT, ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT}, + {HCLGE_SUPPORT_200G_BIT, ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT}, +}; + +static const struct hclge_link_mode_bmap hclge_kr_link_mode_bmap[9] = { + {HCLGE_SUPPORT_1G_BIT, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT}, + {HCLGE_SUPPORT_10G_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, + {HCLGE_SUPPORT_25G_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT}, + {HCLGE_SUPPORT_40G_BIT, ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT}, + {HCLGE_SUPPORT_50G_R2_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT}, + {HCLGE_SUPPORT_50G_R1_BIT, ETHTOOL_LINK_MODE_50000baseKR_Full_BIT}, + {HCLGE_SUPPORT_100G_R4_BIT, ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT}, + {HCLGE_SUPPORT_100G_R2_BIT, ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT}, + {HCLGE_SUPPORT_200G_BIT, ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT}, +}; + static void hclge_convert_setting_sr(u16 speed_ability, unsigned long *link_mode) { - if (speed_ability & HCLGE_SUPPORT_10G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_25G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_40G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_50G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_100G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_200G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, - link_mode); + int i; + + for (i = 0; i < ARRAY_SIZE(hclge_sr_link_mode_bmap); i++) { + if (speed_ability & hclge_sr_link_mode_bmap[i].support_bit) + linkmode_set_bit(hclge_sr_link_mode_bmap[i].link_mode, + link_mode); + } } static void hclge_convert_setting_lr(u16 speed_ability, unsigned long *link_mode) { - if (speed_ability & HCLGE_SUPPORT_10G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_25G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_50G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_40G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_100G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_200G_BIT) - linkmode_set_bit( - ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT, - link_mode); + int i; + + for (i = 0; i < ARRAY_SIZE(hclge_lr_link_mode_bmap); i++) { + if (speed_ability & hclge_lr_link_mode_bmap[i].support_bit) + linkmode_set_bit(hclge_lr_link_mode_bmap[i].link_mode, + link_mode); + } } static void hclge_convert_setting_cr(u16 speed_ability, unsigned long *link_mode) { - if (speed_ability & HCLGE_SUPPORT_10G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_25G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_40G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_50G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_100G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_200G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, - link_mode); + int i; + + for (i = 0; i < ARRAY_SIZE(hclge_cr_link_mode_bmap); i++) { + if (speed_ability & hclge_cr_link_mode_bmap[i].support_bit) + linkmode_set_bit(hclge_cr_link_mode_bmap[i].link_mode, + link_mode); + } } static void hclge_convert_setting_kr(u16 speed_ability, unsigned long *link_mode) { - if (speed_ability & HCLGE_SUPPORT_1G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_10G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_25G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_40G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_50G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_100G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, - link_mode); - if (speed_ability & HCLGE_SUPPORT_200G_BIT) - linkmode_set_bit(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, - link_mode); + int i; + + for (i = 0; i < ARRAY_SIZE(hclge_kr_link_mode_bmap); i++) { + if (speed_ability & hclge_kr_link_mode_bmap[i].support_bit) + linkmode_set_bit(hclge_kr_link_mode_bmap[i].link_mode, + link_mode); + } } static void hclge_convert_setting_fec(struct hclge_mac *mac) @@ -1223,10 +1222,10 @@ static u32 hclge_get_max_speed(u16 speed_ability) if (speed_ability & HCLGE_SUPPORT_200G_BIT) return HCLGE_MAC_SPEED_200G; - if (speed_ability & HCLGE_SUPPORT_100G_BIT) + if (speed_ability & HCLGE_SUPPORT_100G_BITS) return HCLGE_MAC_SPEED_100G; - if (speed_ability & HCLGE_SUPPORT_50G_BIT) + if (speed_ability & HCLGE_SUPPORT_50G_BITS) return HCLGE_MAC_SPEED_50G; if (speed_ability & HCLGE_SUPPORT_40G_BIT) @@ -3045,6 +3044,9 @@ static void hclge_update_link_status(struct hclge_dev *hdev) if (state != hdev->hw.mac.link) { hdev->hw.mac.link = state; + if (state == HCLGE_LINK_STATUS_UP) + hclge_update_port_info(hdev); + client->ops->link_status_change(handle, state); hclge_config_mac_tnl_int(hdev, state); if (rclient && rclient->ops->link_status_change) @@ -10629,8 +10631,6 @@ static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id, struct hclge_vport_vlan_cfg *vlan, *tmp; struct hclge_dev *hdev = vport->back; - mutex_lock(&hdev->vport_lock); - list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) { if (vlan->vlan_id == vlan_id) { if (is_write_tbl && vlan->hd_tbl_status) @@ -10645,8 +10645,6 @@ static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id, break; } } - - mutex_unlock(&hdev->vport_lock); } void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list) @@ -11062,11 +11060,16 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, * handle mailbox. Just record the vlan id, and remove it after * reset finished. */ + mutex_lock(&hdev->vport_lock); if ((test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) || test_bit(HCLGE_STATE_RST_FAIL, &hdev->state)) && is_kill) { set_bit(vlan_id, vport->vlan_del_fail_bmap); + mutex_unlock(&hdev->vport_lock); return -EBUSY; + } else if (!is_kill && test_bit(vlan_id, vport->vlan_del_fail_bmap)) { + clear_bit(vlan_id, vport->vlan_del_fail_bmap); } + mutex_unlock(&hdev->vport_lock); /* when port base vlan enabled, we use port base vlan as the vlan * filter entry. In this case, we don't update vlan filter table @@ -11081,17 +11084,22 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, } if (!ret) { - if (!is_kill) + if (!is_kill) { hclge_add_vport_vlan_table(vport, vlan_id, writen_to_tbl); - else if (is_kill && vlan_id != 0) + } else if (is_kill && vlan_id != 0) { + mutex_lock(&hdev->vport_lock); hclge_rm_vport_vlan_table(vport, vlan_id, false); + mutex_unlock(&hdev->vport_lock); + } } else if (is_kill) { /* when remove hw vlan filter failed, record the vlan id, * and try to remove it from hw later, to be consistence * with stack */ + mutex_lock(&hdev->vport_lock); set_bit(vlan_id, vport->vlan_del_fail_bmap); + mutex_unlock(&hdev->vport_lock); } hclge_set_vport_vlan_fltr_change(vport); @@ -11131,6 +11139,7 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev) int i, ret, sync_cnt = 0; u16 vlan_id; + mutex_lock(&hdev->vport_lock); /* start from vport 1 for PF is always alive */ for (i = 0; i < hdev->num_alloc_vport; i++) { struct hclge_vport *vport = &hdev->vport[i]; @@ -11141,21 +11150,26 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev) ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q), vport->vport_id, vlan_id, true); - if (ret && ret != -EINVAL) + if (ret && ret != -EINVAL) { + mutex_unlock(&hdev->vport_lock); return; + } clear_bit(vlan_id, vport->vlan_del_fail_bmap); hclge_rm_vport_vlan_table(vport, vlan_id, false); hclge_set_vport_vlan_fltr_change(vport); sync_cnt++; - if (sync_cnt >= HCLGE_MAX_SYNC_COUNT) + if (sync_cnt >= HCLGE_MAX_SYNC_COUNT) { + mutex_unlock(&hdev->vport_lock); return; + } vlan_id = find_first_bit(vport->vlan_del_fail_bmap, VLAN_N_VID); } } + mutex_unlock(&hdev->vport_lock); hclge_sync_vlan_fltr_state(hdev); } @@ -12421,6 +12435,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) goto err_msi_irq_uninit; if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) { + clear_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps); if (hnae3_dev_phy_imp_supported(hdev)) ret = hclge_update_tp_port_info(hdev); else diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index cc373064f198f0637c28a3cee0cd017bff86fb59..2261e7b407c610979a635ca7a1195bc91ab51047 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -189,15 +189,22 @@ enum HLCGE_PORT_TYPE { #define HCLGE_SUPPORT_1G_BIT BIT(0) #define HCLGE_SUPPORT_10G_BIT BIT(1) #define HCLGE_SUPPORT_25G_BIT BIT(2) -#define HCLGE_SUPPORT_50G_BIT BIT(3) -#define HCLGE_SUPPORT_100G_BIT BIT(4) +#define HCLGE_SUPPORT_50G_R2_BIT BIT(3) +#define HCLGE_SUPPORT_100G_R4_BIT BIT(4) /* to be compatible with exsit board */ #define HCLGE_SUPPORT_40G_BIT BIT(5) #define HCLGE_SUPPORT_100M_BIT BIT(6) #define HCLGE_SUPPORT_10M_BIT BIT(7) #define HCLGE_SUPPORT_200G_BIT BIT(8) +#define HCLGE_SUPPORT_50G_R1_BIT BIT(9) +#define HCLGE_SUPPORT_100G_R2_BIT BIT(10) + #define HCLGE_SUPPORT_GE \ (HCLGE_SUPPORT_1G_BIT | HCLGE_SUPPORT_100M_BIT | HCLGE_SUPPORT_10M_BIT) +#define HCLGE_SUPPORT_50G_BITS \ + (HCLGE_SUPPORT_50G_R2_BIT | HCLGE_SUPPORT_50G_R1_BIT) +#define HCLGE_SUPPORT_100G_BITS \ + (HCLGE_SUPPORT_100G_R4_BIT | HCLGE_SUPPORT_100G_R2_BIT) enum HCLGE_DEV_STATE { HCLGE_STATE_REINITING, @@ -1112,6 +1119,11 @@ struct hclge_mac_speed_map { u32 speed_fw; /* speed defined in firmware */ }; +struct hclge_link_mode_bmap { + u16 support_bit; + enum ethtool_link_mode_bit_indices link_mode; +}; + int hclge_set_vport_promisc_mode(struct hclge_vport *vport, bool en_uc_pmc, bool en_mc_pmc, bool en_bc_pmc); int hclge_add_uc_addr_common(struct hclge_vport *vport, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 52fb9dfdd724ebcb9481ebd3d405f299acb1d9a3..34dcaf4f1bda819cb5571e6f1e03f7347014f777 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1326,6 +1326,8 @@ static int hclgevf_set_vlan_filter(struct hnae3_handle *handle, test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state)) && is_kill) { set_bit(vlan_id, hdev->vlan_del_fail_bmap); return -EBUSY; + } else if (!is_kill && test_bit(vlan_id, hdev->vlan_del_fail_bmap)) { + clear_bit(vlan_id, hdev->vlan_del_fail_bmap); } hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN, @@ -1353,20 +1355,25 @@ static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev) int ret, sync_cnt = 0; u16 vlan_id; + if (bitmap_empty(hdev->vlan_del_fail_bmap, VLAN_N_VID)) + return; + + rtnl_lock(); vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID); while (vlan_id != VLAN_N_VID) { ret = hclgevf_set_vlan_filter(handle, htons(ETH_P_8021Q), vlan_id, true); if (ret) - return; + break; clear_bit(vlan_id, hdev->vlan_del_fail_bmap); sync_cnt++; if (sync_cnt >= HCLGEVF_MAX_SYNC_COUNT) - return; + break; vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID); } + rtnl_unlock(); } static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) @@ -2122,8 +2129,18 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, return HCLGEVF_VECTOR0_EVENT_OTHER; } +static void hclgevf_reset_timer(struct timer_list *t) +{ + struct hclgevf_dev *hdev = from_timer(hdev, t, reset_timer); + + hclgevf_clear_event_cause(hdev, HCLGEVF_VECTOR0_EVENT_RST); + hclgevf_reset_task_schedule(hdev); +} + static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data) { +#define HCLGEVF_RESET_DELAY 5 + enum hclgevf_evt_cause event_cause; struct hclgevf_dev *hdev = data; u32 clearval; @@ -2135,7 +2152,8 @@ static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data) switch (event_cause) { case HCLGEVF_VECTOR0_EVENT_RST: - hclgevf_reset_task_schedule(hdev); + mod_timer(&hdev->reset_timer, + jiffies + msecs_to_jiffies(HCLGEVF_RESET_DELAY)); break; case HCLGEVF_VECTOR0_EVENT_MBX: hclgevf_mbx_handler(hdev); @@ -3143,6 +3161,7 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) HCLGEVF_DRIVER_NAME); hclgevf_task_schedule(hdev, round_jiffies_relative(HZ)); + timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0); return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 699a2afaef0ec646abc85907803c24ff60a5d1f7..0010c15835e28eb99402cdec9ba853704d5ef4ab 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -230,6 +230,7 @@ struct hclgevf_dev { enum hnae3_reset_type reset_level; unsigned long reset_pending; enum hnae3_reset_type reset_type; + struct timer_list reset_timer; #define HCLGEVF_RESET_REQUESTED 0 #define HCLGEVF_RESET_PENDING 1 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c index 2c7c5e7d4fe7b52629a28c18a476f49eea12f1b6..6ccf23ce2744055449204936ac5607e1248bfcc6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c @@ -63,6 +63,9 @@ static int hclgevf_get_mbx_resp(struct hclgevf_dev *hdev, u16 code0, u16 code1, i++; } + /* ensure additional_info will be seen after received_resp */ + smp_rmb(); + if (i >= HCLGEVF_MAX_TRY_TIMES) { dev_err(&hdev->pdev->dev, "VF could not get mbx(%u,%u) resp(=%d) from PF in %d tries\n", @@ -178,6 +181,10 @@ static void hclgevf_handle_mbx_response(struct hclgevf_dev *hdev, resp->resp_status = hclgevf_resp_to_errno(resp_status); memcpy(resp->additional_info, req->msg.resp_data, HCLGE_MBX_MAX_RESP_DATA_SIZE * sizeof(u8)); + + /* ensure additional_info will be seen before setting received_resp */ + smp_wmb(); + if (match_id) { /* If match_id is not zero, it means PF support match_id. * if the match_id is right, VF get the right response, or diff --git a/drivers/perf/hisilicon/hns3_pmu.c b/drivers/perf/hisilicon/hns3_pmu.c index 45d0b17d19da1d7548391598456265bfd1a6f417..f1934192f3a8e73ffe554778241464a5640fc04c 100644 --- a/drivers/perf/hisilicon/hns3_pmu.c +++ b/drivers/perf/hisilicon/hns3_pmu.c @@ -1563,7 +1563,7 @@ static int hns3_pmu_init_pmu(struct pci_dev *pdev, struct hns3_pmu *hns3_pmu) ret = perf_pmu_register(&hns3_pmu->pmu, hns3_pmu->pmu.name, -1); if (ret) { pci_err(pdev, "failed to register perf PMU, ret = %d.\n", ret); - cpuhp_state_remove_instance(hns3_pmu_online, &hns3_pmu->node); + cpuhp_state_remove_instance_nocalls(hns3_pmu_online, &hns3_pmu->node); } return ret; @@ -1574,7 +1574,7 @@ static void hns3_pmu_uninit_pmu(struct pci_dev *pdev) struct hns3_pmu *hns3_pmu = pci_get_drvdata(pdev); perf_pmu_unregister(&hns3_pmu->pmu); - cpuhp_state_remove_instance(hns3_pmu_online, &hns3_pmu->node); + cpuhp_state_remove_instance_nocalls(hns3_pmu_online, &hns3_pmu->node); } static int hns3_pmu_init_dev(struct pci_dev *pdev)