From 0b68f4778af4fded021ba67f5eb3fb74ff8d7fc1 Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Fri, 20 Oct 2023 15:00:17 +0800 Subject: [PATCH 01/11] net: hns3: support arp proxy driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GQDK CVE: NA ---------------------------------------------------------------------- In RoH mode, the IP and MAC of network devices have a special mapping relationship. The mapping is show as followed: IP: a.b.c.d <------> MAC: 0.0.0.b.c.d Thus, the arp request for find the mac of a ip is not necessary to send to network. The driver can generate a response arp to the protocol stack based on above mapping relationship. Arp proxy is designed to acheive the above function. The scope of ARP proxy include all ARP request message including vlan, except free ARP request and tunnel message. Signed-off-by: Peiyang Wang --- drivers/net/ethernet/hisilicon/hns3/Makefile | 2 +- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 6 + .../net/ethernet/hisilicon/hns3/hns3_enet.h | 14 ++ .../net/ethernet/hisilicon/hns3/hns3_roh.c | 174 ++++++++++++++++++ .../net/ethernet/hisilicon/hns3/hns3_roh.h | 24 +++ 5 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_roh.c create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_roh.h diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile index bd5aea7dd490..5f188d5c3d9d 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/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index abbfe7a4117f..3c3908344912 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,9 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) hns3_unic_set_default_cc(skb); } #endif + if (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 +4825,8 @@ 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); + 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); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 498103e4884d..c0237202feae 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_roh.c b/drivers/net/ethernet/hisilicon/hns3/hns3_roh.c new file mode 100644 index 000000000000..b0fa565ba36f --- /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 000000000000..2ea8c6a29441 --- /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 -- Gitee From 90993e84450b0df9bdd9164110294c993d66b9ab Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Mon, 23 Oct 2023 15:03:26 +0800 Subject: [PATCH 02/11] net: hns3: add arp proxy switch in ethtool driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GQDK CVE: NA ---------------------------------------------------------------------- To use arp proxy more conviency, add an arp proxy switch in ethool. Use followed command to open or close arp proxy: ethtool --set-priv-flags roh_arp_proxy_enable Use followed command to find current state of arp proxy switch: ethtool --show-priv-flags The results are showed as followed: ... roh_arp_proxy_enable: on Upstream: Yes Bugfix or Feature: Feature AR20230919193847 Signed-off-by: Peiyang Wang --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 13 +++++++++++-- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 8 ++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 124ba9dca6b0..ec23633c49b2 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_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 3c3908344912..32a984028caf 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2589,7 +2589,9 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) hns3_unic_set_default_cc(skb); } #endif - if (hns3_need_to_handle_roh_arp_req(skb)) + 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); @@ -4825,7 +4827,8 @@ 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); - hns3_handle_roh_arp_reply(tqp_vector, priv); + 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, @@ -5627,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_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index c0afdc1af05a..50661a3f6d3f 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) -- Gitee From 6868fba5037ecc2436c0227d0b3ec2f60a337d2e Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Tue, 24 Oct 2023 11:20:34 +0800 Subject: [PATCH 03/11] net: hns3: add some link modes for hisilicon device mainline inclusion from mainline-v6.7-rc1 commit 8ee2843f4d52026ab67e7577eaa49d444e1976b8 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8E4XS CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8ee2843f4d52026ab67e7577eaa49d444e1976b8 ---------------------------------------------------------------------- Add HCLGE_SUPPORT_50G_R1_BIT and HCLGE_SUPPORT_100G_R2_BIT two capability bits and Corresponding link modes. Signed-off-by: Hao Chen Signed-off-by: Jijie Shao Reviewed-by: Wojciech Drewek Signed-off-by: David S. Miller Signed-off-by: Jiantao Xiao --- .../hisilicon/hns3/hns3pf/hclge_main.c | 158 +++++++++--------- .../hisilicon/hns3/hns3pf/hclge_main.h | 16 +- 2 files changed, 92 insertions(+), 82 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 87fdc6a0931a..6221e761da43 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -946,8 +946,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 +1004,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 +1221,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) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index cc373064f198..2261e7b407c6 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, -- Gitee From 5e763f62ef18411ce7040c50ab23c10750fff804 Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Thu, 19 Oct 2023 17:13:52 +0800 Subject: [PATCH 04/11] drivers/perf: hisi: use cpuhp_state_remove_instance_nocalls() for hisi_hns3_pmu uninit process driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8E4FG CVE: NA ---------------------------------------------------------------------- When tearing down a 'hisi_hns3' PMU, we mistakenly run the CPU hotplug callbacks after the device has been unregistered, leading to fireworks when we try to execute empty function callbacks within the driver: | Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 | CPU: 0 PID: 15 Comm: cpuhp/0 Tainted: G W O 5.12.0-rc4+ #1 | Hardware name: , BIOS KpxxxFPGA 1P B600 V143 04/22/2021 | pstate: 80400009 (Nzcv daif +PAN -UAO -TCO BTYPE=--) | pc : perf_pmu_migrate_context+0x98/0x38c | lr : perf_pmu_migrate_context+0x94/0x38c | | Call trace: | perf_pmu_migrate_context+0x98/0x38c | hisi_hns3_pmu_offline_cpu+0x104/0x12c [hisi_hns3_pmu] Use cpuhp_state_remove_instance_nocalls() instead of cpuhp_state_remove_instance() so that the notifiers don't execute after the PMU device has been unregistered. Fixes: 66637ab137b4 ("drivers/perf: hisi: add driver for HNS3 PMU") Signed-off-by: Hao Chen Signed-off-by: Jijie Shao Signed-off-by: Jiantao Xiao --- drivers/perf/hisilicon/hns3_pmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/perf/hisilicon/hns3_pmu.c b/drivers/perf/hisilicon/hns3_pmu.c index 45d0b17d19da..f1934192f3a8 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) -- Gitee From ed4c58f9fb5f037619fec28a5b6052552bc0bf1b Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Fri, 10 Nov 2023 17:37:07 +0800 Subject: [PATCH 05/11] net: hns3: fix add VLAN fail issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit maillist inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GVK7 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=472a2ff63efb30234cbf6b2cdaf8117f21b4f8bc ---------------------------------------------------------------------- The hclge_sync_vlan_filter is called in periodic task, trying to remove VLAN from vlan_del_fail_bmap. It can be concurrence with VLAN adding operation from user. So once user failed to delete a VLAN id, and add it again soon, it may be removed by the periodic task, which may cause the software configuration being inconsistent with hardware. So add mutex handling to avoid this. user hns3 driver periodic task │ add vlan 10 ───── hns3_vlan_rx_add_vid │ │ (suppose success) │ │ │ del vlan 10 ───── hns3_vlan_rx_kill_vid │ │ (suppose fail,add to │ │ vlan_del_fail_bmap) │ │ │ add vlan 10 ───── hns3_vlan_rx_add_vid │ (suppose success) │ foreach vlan_del_fail_bmp del vlan 10 Fixes: fe4144d47eef ("net: hns3: sync VLAN filter entries when kill VLAN ID failed") Signed-off-by: Jian Shen Signed-off-by: Jijie Shao Signed-off-by: David S. Miller Signed-off-by: Jiantao Xiao --- .../hisilicon/hns3/hns3pf/hclge_main.c | 28 +++++++++++++------ .../hisilicon/hns3/hns3vf/hclgevf_main.c | 11 ++++++-- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 6221e761da43..5c85aac24283 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -10627,8 +10627,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) @@ -10643,8 +10641,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) @@ -11060,11 +11056,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 @@ -11079,17 +11080,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); @@ -11129,6 +11135,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]; @@ -11139,21 +11146,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); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 52fb9dfdd724..c5f7f3703a36 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) -- Gitee From e8664a41374b0185985074f29a3b442d53aa2e80 Mon Sep 17 00:00:00 2001 From: Yonglong Liu Date: Fri, 10 Nov 2023 17:37:08 +0800 Subject: [PATCH 06/11] net: hns3: add barrier in vf mailbox reply process maillist inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GVK7 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ac92c0a9a0603fb448e60f38e63302e4eebb8035 ---------------------------------------------------------------------- In hclgevf_mbx_handler() and hclgevf_get_mbx_resp() functions, there is a typical store-store and load-load scenario between received_resp and additional_info. This patch adds barrier to fix the problem. Fixes: 4671042f1ef0 ("net: hns3: add match_id to check mailbox response from PF to VF") Signed-off-by: Yonglong Liu Signed-off-by: Jijie Shao Signed-off-by: David S. Miller Signed-off-by: Jiantao Xiao --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c index 2c7c5e7d4fe7..6ccf23ce2744 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 -- Gitee From f4d0dd6185d52f673076092ffde3fdbca9c6f016 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Fri, 10 Nov 2023 17:37:09 +0800 Subject: [PATCH 07/11] net: hns3: fix incorrect capability bit display for copper port maillist inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GVK7 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=75b247b57d8b71bcb679e4cb37d0db104848806c ---------------------------------------------------------------------- Currently, the FEC capability bit is default set for device version V2. It's incorrect for the copper port. Eventhough it doesn't make the nic work abnormal, but the capability information display in debugfs may confuse user. So clear it when driver get the port type inforamtion. Fixes: 433ccce83504 ("net: hns3: use FEC capability queried from firmware") Signed-off-by: Jian Shen Signed-off-by: Jijie Shao Signed-off-by: David S. Miller Signed-off-by: Jiantao Xiao --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 5c85aac24283..2be239030001 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -12431,6 +12431,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 -- Gitee From 766fbcb38907c9fa37cf08a43ef95656d70887e8 Mon Sep 17 00:00:00 2001 From: Yonglong Liu Date: Fri, 10 Nov 2023 17:37:10 +0800 Subject: [PATCH 08/11] net: hns3: fix out-of-bounds access may occur when coalesce info is read via debugfs maillist inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GVK7 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=53aba458f23846112c0d44239580ff59bc5c36c3 ---------------------------------------------------------------------- The hns3 driver define an array of string to show the coalesce info, but if the kernel adds a new mode or a new state, out-of-bounds access may occur when coalesce info is read via debugfs, this patch fix the problem. Fixes: c99fead7cb07 ("net: hns3: add debugfs support for interrupt coalesce") Signed-off-by: Yonglong Liu Signed-off-by: Jijie Shao Signed-off-by: David S. Miller Signed-off-by: Jiantao Xiao --- drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 5cdfa8e06ddf..403a34a422bc 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); -- Gitee From 5540c6584d3bd77914e9e33a9599f97a43e20d4f Mon Sep 17 00:00:00 2001 From: Yonglong Liu Date: Fri, 10 Nov 2023 17:37:11 +0800 Subject: [PATCH 09/11] net: hns3: fix variable may not initialized problem in hns3_init_mac_addr() maillist inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GVK7 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=dbd2f3b20c6ae425665b6975d766e3653d453e73 ---------------------------------------------------------------------- When a VF is calling hns3_init_mac_addr(), get_mac_addr() may return fail, then the value of mac_addr_temp is not initialized. Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC") Signed-off-by: Yonglong Liu Signed-off-by: Jijie Shao Signed-off-by: David S. Miller Signed-off-by: Jiantao Xiao --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 32a984028caf..de2c2d8a9536 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -5484,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)) -- Gitee From 4af9d3d5fec5b2f9af56b758e58e88edb5ebbfe5 Mon Sep 17 00:00:00 2001 From: Jijie Shao Date: Fri, 10 Nov 2023 17:37:12 +0800 Subject: [PATCH 10/11] net: hns3: fix VF reset fail issue maillist inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GVK7 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=65e98bb56fa3ce2edb400930c05238c9b380500e ---------------------------------------------------------------------- Currently the reset process in hns3 and firmware watchdog init process is asynchronous. We think firmware watchdog initialization is completed before VF clear the interrupt source. However, firmware initialization may not complete early. So VF will receive multiple reset interrupts and fail to reset. So we add delay before VF interrupt source and 5 ms delay is enough to avoid second reset interrupt. Fixes: 427900d27d86 ("net: hns3: fix the timing issue of VF clearing interrupt sources") Signed-off-by: Jijie Shao Signed-off-by: David S. Miller Signed-off-by: Jiantao Xiao --- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 14 +++++++++++++- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index c5f7f3703a36..34dcaf4f1bda 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2129,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; @@ -2142,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); @@ -3150,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 699a2afaef0e..0010c15835e2 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 -- Gitee From 998b0ab9f4023ef2f90e2d6a71b386f90ee57c5c Mon Sep 17 00:00:00 2001 From: Jijie Shao Date: Fri, 10 Nov 2023 17:37:13 +0800 Subject: [PATCH 11/11] net: hns3: fix VF wrong speed and duplex issue maillist inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8GVK7 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=dff655e82faffc287d4a72a59f66fa120bf904e4 ---------------------------------------------------------------------- If PF is down, firmware will returns 10 Mbit/s rate and half-duplex mode when PF queries the port information from firmware. After imp reset command is executed, PF status changes to down, and PF will query link status and updates port information from firmware in a periodic scheduled task. However, there is a low probability that port information is updated when PF is down, and then PF link status changes to up. In this case, PF synchronizes incorrect rate and duplex mode to VF. This patch fixes it by updating port information before PF synchronizes the rate and duplex to the VF when PF changes to up. Fixes: 18b6e31f8bf4 ("net: hns3: PF add support for pushing link status to VFs") Signed-off-by: Jijie Shao Signed-off-by: David S. Miller Signed-off-by: Jiantao Xiao --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 2be239030001..3b6278eafc0c 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; @@ -3043,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) -- Gitee