From 30ab754f921dce70c18373ae13685edb150948f1 Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Mon, 21 Apr 2025 10:42:43 +0800 Subject: [PATCH 01/12] net: hns3: add ieee_setmaxrate and ieee_getmaxrate support for pf driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- Add support for ieee_setmaxrate and ieee_getmaxrate. The minimum rate supported by the hardware is 1 Mbit/s. Signed-off-by: Jian Shen Signed-off-by: Hao Lan Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 4 ++ .../net/ethernet/hisilicon/hns3/hns3_dcbnl.c | 24 ++++++++ .../hisilicon/hns3/hns3pf/hclge_dcb.c | 58 +++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_dcb.h | 3 + .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 2 +- 5 files changed, 90 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 7f22240c9055..bccb1ddc099a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -852,6 +852,10 @@ struct hnae3_dcb_ops { int (*ieee_setpfc)(struct hnae3_handle *, struct ieee_pfc *); int (*ieee_setapp)(struct hnae3_handle *h, struct dcb_app *app); int (*ieee_delapp)(struct hnae3_handle *h, struct dcb_app *app); + int (*ieee_setmaxrate)(struct hnae3_handle *h, + struct ieee_maxrate *maxrate); + int (*ieee_getmaxrate)(struct hnae3_handle *h, + struct ieee_maxrate *maxrate); /* DCBX configuration */ u8 (*getdcbx)(struct hnae3_handle *); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c index f72dc0cee30e..19fef1d41701 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c @@ -104,6 +104,28 @@ static u8 hns3_dcbnl_setdcbx(struct net_device *ndev, u8 mode) return 1; } +static int hns3_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct ieee_maxrate *maxrate) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (h->kinfo.dcb_ops->ieee_setmaxrate) + return h->kinfo.dcb_ops->ieee_setmaxrate(h, maxrate); + + return -EOPNOTSUPP; +} + +static int hns3_dcbnl_ieee_getmaxrate(struct net_device *netdev, + struct ieee_maxrate *maxrate) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (h->kinfo.dcb_ops->ieee_getmaxrate) + return h->kinfo.dcb_ops->ieee_getmaxrate(h, maxrate); + + return -EOPNOTSUPP; +} + static const struct dcbnl_rtnl_ops hns3_dcbnl_ops = { .ieee_getets = hns3_dcbnl_ieee_getets, .ieee_setets = hns3_dcbnl_ieee_setets, @@ -111,6 +133,8 @@ static const struct dcbnl_rtnl_ops hns3_dcbnl_ops = { .ieee_setpfc = hns3_dcbnl_ieee_setpfc, .ieee_setapp = hns3_dcbnl_ieee_setapp, .ieee_delapp = hns3_dcbnl_ieee_delapp, + .ieee_setmaxrate = hns3_dcbnl_ieee_setmaxrate, + .ieee_getmaxrate = hns3_dcbnl_ieee_getmaxrate, .getdcbx = hns3_dcbnl_getdcbx, .setdcbx = hns3_dcbnl_setdcbx, }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 416bcac3bf70..140db47c2055 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -509,6 +509,62 @@ static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode) return 0; } +static int hclge_ieee_getmaxrate(struct hnae3_handle *h, + struct ieee_maxrate *maxrate) +{ + struct hnae3_tc_info *tc_info = &h->kinfo.tc_info; + + memcpy(maxrate, tc_info->max_rate, sizeof(struct ieee_maxrate)); + return 0; +} + +static int hclge_check_maxrate(struct hclge_dev *hdev, + struct ieee_maxrate *maxrate) +{ + u64 max_speed = (u64)hdev->hw.mac.max_speed * TM_RATE_PORT_RATE_SCALE; + u8 i; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + /* no limit */ + if (!maxrate->tc_maxrate[i]) + continue; + if (maxrate->tc_maxrate[i] < TM_RATE_PORT_RATE_SCALE || + maxrate->tc_maxrate[i] > max_speed) { + dev_err(&hdev->pdev->dev, + "invalid max_rate[%llubps]: the range is [1Mbps, %uMbps]\n", + maxrate->tc_maxrate[i] * HCLGE_BYTE_BITS, + hdev->hw.mac.max_speed); + return -EINVAL; + } + } + return 0; +} + +static int hclge_ieee_setmaxrate(struct hnae3_handle *h, + struct ieee_maxrate *maxrate) +{ + struct hnae3_tc_info *tc_info = &h->kinfo.tc_info; + struct hclge_vport *vport = hclge_get_vport(h); + struct hclge_dev *hdev = vport->back; + struct hnae3_tc_info old_tc_info; + int ret; + + if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || tc_info->mqprio_active) + return -EINVAL; + + ret = hclge_check_maxrate(hdev, maxrate); + if (ret) + return ret; + + old_tc_info = *tc_info; + memcpy(tc_info->max_rate, maxrate, sizeof(struct ieee_maxrate)); + ret = hclge_tm_set_tc_rate_limit(hdev, tc_info); + if (ret) + *tc_info = old_tc_info; + + return ret; +} + static int hclge_mqprio_qopt_check_rate(struct hclge_dev *hdev, u64 min_rate, u64 max_rate) { @@ -702,6 +758,8 @@ static const struct hnae3_dcb_ops hns3_dcb_ops = { .getdcbx = hclge_getdcbx, .setdcbx = hclge_setdcbx, .setup_tc = hclge_setup_tc, + .ieee_setmaxrate = hclge_ieee_setmaxrate, + .ieee_getmaxrate = hclge_ieee_getmaxrate, }; void hclge_dcb_ops_set(struct hclge_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h index b04702e65689..23e35c643c15 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h @@ -12,4 +12,7 @@ void hclge_dcb_ops_set(struct hclge_dev *hdev); static inline void hclge_dcb_ops_set(struct hclge_dev *hdev) {} #endif +#define HCLGE_BYTE_BITS 8ULL +#define HCLGE_RATE_UNIT_MBPS 1000000ULL /* 1Mbps */ + #endif /* __HCLGE_DCB_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index a8350940fd5e..60a133626037 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1734,7 +1734,7 @@ int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) if (ret) return ret; - if (hnae3_dev_roh_supported(hdev)) + if (hdev->ae_dev->dev_version > HNAE3_DEVICE_VERSION_V2) return hclge_tm_set_tc_rate_limit(hdev, tc_info); return 0; -- Gitee From bed681be57a64194508867da2fbc05cb72fa5417 Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Fri, 25 Apr 2025 11:31:19 +0800 Subject: [PATCH 02/12] net: hns3: merge rss tc configuration driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- Merge hclge_comm_get_rss_tc_info() and hclge_comm_get_rss_tc_info() to a new function hclge_comm_get_rss_tc_info(), so it doesn't need to define tc arrays every where. Signed-off-by: Jian Shen Signed-off-by: Hao Lan Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- .../hisilicon/hns3/hns3vf/hclgevf_main.c | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 3f137cb15847..222c828b9e5d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2256,12 +2256,21 @@ static int hclgevf_config_gro(struct hclgevf_dev *hdev) return ret; } +static int hclgevf_init_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) +{ + u16 tc_offset[HNAE3_MAX_TC] = {0}; + u16 tc_valid[HNAE3_MAX_TC] = {0}; + u16 tc_size[HNAE3_MAX_TC] = {0}; + + hclge_comm_get_rss_tc_info(rss_size, hdev->hw_tc_map, + tc_offset, tc_valid, tc_size); + return hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, tc_valid, + tc_size); +} + static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) { struct hclge_comm_rss_cfg *rss_cfg = &hdev->rss_cfg; - u16 tc_offset[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_valid[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_size[HCLGE_COMM_MAX_TC_NUM]; int ret; if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { @@ -2281,11 +2290,7 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) if (ret) return ret; - hclge_comm_get_rss_tc_info(rss_cfg->rss_size, hdev->hw_tc_map, - tc_offset, tc_valid, tc_size); - - return hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, - tc_valid, tc_size); + return hclgevf_init_rss_tc_mode(hdev, rss_cfg->rss_size); } static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev, @@ -3238,9 +3243,6 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); struct hnae3_knic_private_info *kinfo = &handle->kinfo; - u16 tc_offset[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_valid[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_size[HCLGE_COMM_MAX_TC_NUM]; u16 cur_rss_size = kinfo->rss_size; u16 cur_tqps = kinfo->num_tqps; u32 *rss_indir; @@ -3249,10 +3251,7 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, hclgevf_update_rss_size(handle, new_tqps_num); - hclge_comm_get_rss_tc_info(kinfo->rss_size, hdev->hw_tc_map, - tc_offset, tc_valid, tc_size); - ret = hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, - tc_valid, tc_size); + ret = hclgevf_init_rss_tc_mode(hdev, kinfo->rss_size); if (ret) return ret; -- Gitee From 62334cb38226f079c5e497d6dde6dc388122e283 Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Fri, 25 Apr 2025 11:32:50 +0800 Subject: [PATCH 03/12] net: hns3: add support to query tc map info of VF queues driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- Modified hclge_tm_get_q_to_tc to support the query of TC map info of VF queues. Signed-off-by: Jian Shen Signed-off-by: Hao Lan Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 7 ++++++- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 60a133626037..da3d135a6e25 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -2033,12 +2033,17 @@ int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id) #define HCLGE_TM_TC_MASK 0x7 struct hclge_tqp_tx_queue_tc_cmd *tc; + struct hclge_vport *vport; struct hclge_desc desc; int ret; + vport = container_of(hdev->htqp[q_id].q.handle, + struct hclge_vport, nic); tc = (struct hclge_tqp_tx_queue_tc_cmd *)desc.data; hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TQP_TX_QUEUE_TC, true); - tc->queue_id = cpu_to_le16(q_id); + tc->queue_id = cpu_to_le16(hdev->htqp[q_id].q.tqp_index); + tc->func_id = (u8)vport->vport_id; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index 64b448370f93..b3c81050394e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -65,9 +65,10 @@ struct hclge_nq_to_qs_link_cmd { struct hclge_tqp_tx_queue_tc_cmd { __le16 queue_id; - __le16 rsvd; + u8 func_id; + u8 rsvd1; u8 tc_id; - u8 rev[3]; + u8 rsvd2[3]; }; struct hclge_pg_weight_cmd { -- Gitee From a5fc3788ad773ada3a039078c2de24166d5028ac Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Tue, 6 May 2025 10:54:48 +0800 Subject: [PATCH 04/12] net: hns3: using the num_tqps in the vf driver to apply for resources driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- using the num_tqps in the vf driver to apply for resources instead of private info Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 222c828b9e5d..7696b1963186 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -370,12 +370,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) new_tqps = kinfo->rss_size * num_tc; kinfo->num_tqps = min(new_tqps, hdev->num_tqps); - kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, + kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, sizeof(struct hnae3_queue *), GFP_KERNEL); if (!kinfo->tqp) return -ENOMEM; - for (i = 0; i < kinfo->num_tqps; i++) { + for (i = 0; i < hdev->num_tqps; i++) { hdev->htqp[i].q.handle = &hdev->nic; hdev->htqp[i].q.tqp_index = i; kinfo->tqp[i] = &hdev->htqp[i].q; -- Gitee From a42b779f155379d9a83a093b8287d2a20510f0ba Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Fri, 9 May 2025 14:50:34 +0800 Subject: [PATCH 05/12] net: hns3: using the num_tqps to check whether tqp_index is out of range when vf get ring info from mbx driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- using the num_tqps to check whether tqp_index is out of range, instead of rss_size. Fixes: 326334aad024 ("net: hns3: add a check for tqp_index in hclge_get_ring_chain_from_mbx()") Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 7b3709f480b3..fdba02a46968 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -193,10 +193,10 @@ static int hclge_get_ring_chain_from_mbx( return -EINVAL; for (i = 0; i < ring_num; i++) { - if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { + if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) { dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", req->msg.param[i].tqp_index, - vport->nic.kinfo.rss_size - 1U); + vport->nic.kinfo.num_tqps - 1U); return -EINVAL; } } -- Gitee From 95aa6fcdae69d0716cebd65238a450905776d2ee Mon Sep 17 00:00:00 2001 From: Jijie Shao Date: Thu, 3 Jul 2025 16:00:27 +0800 Subject: [PATCH 06/12] net: hns3: Return error code when function fails. driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- Currently, in hclge_mii_ioctl(), the operation to read the PHY register (SIOCGMIIREG) always returns 0. This patch changes the return type of hclge_read_phy_reg(), returning an error code when the function fails. Fixes: 91b783894309 ("net: hns3: add ioctl support for imp-controlled PHYs") Signed-off-by: Jijie Shao Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +-- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 9 ++++++--- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 971340509b0d..a5029f957b09 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -10136,8 +10136,7 @@ static int hclge_mii_ioctl(struct hclge_dev *hdev, struct ifreq *ifr, int cmd) /* this command reads phy id and register at the same time */ fallthrough; case SIOCGMIIREG: - data->val_out = hclge_read_phy_reg(hdev, data->reg_num); - return 0; + return hclge_read_phy_reg(hdev, data->reg_num, &data->val_out); case SIOCSMIIREG: return hclge_write_phy_reg(hdev, data->reg_num, data->val_in); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index e8b263a1f66f..17aa7fcd0706 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -274,7 +274,7 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev) phy_stop(phydev); } -u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr) +int hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 *val) { struct hclge_phy_reg_cmd *req; struct hclge_desc desc; @@ -286,11 +286,14 @@ u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr) req->reg_addr = cpu_to_le16(reg_addr); ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) + if (ret) { dev_err(&hdev->pdev->dev, "failed to read phy reg, ret = %d.\n", ret); + return ret; + } - return le16_to_cpu(req->reg_val); + *val = le16_to_cpu(req->reg_val); + return 0; } int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h index 4200d0b6d931..21d434c82475 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h @@ -13,7 +13,7 @@ int hclge_mac_connect_phy(struct hnae3_handle *handle); void hclge_mac_disconnect_phy(struct hnae3_handle *handle); void hclge_mac_start_phy(struct hclge_dev *hdev); void hclge_mac_stop_phy(struct hclge_dev *hdev); -u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr); +int hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 *val); int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val); #endif -- Gitee From 91bf70b00897f667d28be32b0633ce6a94288693 Mon Sep 17 00:00:00 2001 From: Shuaisong Yang Date: Wed, 9 Jul 2025 11:01:09 +0800 Subject: [PATCH 07/12] net: hns3: use user configure after hardware reset when using kernel PHY. driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- When a reset occurring, it's supposed to recover user's configuration. Consider the case that reset was happened consecutively. During the first reset, the port info is configured with a temporary value cause the PHY is reset and looking for best link config. Second reset start and use pervious configuration which is not the user's. Therefore, in this case, the network port may not link up. In this patch, saving user configure to req_xxx variable after successful configuration when using kernel PHY or firmware PHY. And then, use the req_xxx variable after hardware reset. Compared to the previous commit "net: hns3: using user configure after hardware reset", it adds handling for kernel PHY and FIBER. Fixes: 21a2659e2c1e ("net: hns3: using user configure after hardware reset") Signed-off-by: Shuaisong Yang Signed-off-by: Donghua Huang --- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 26 ++++----- .../hisilicon/hns3/hns3pf/hclge_main.c | 56 ++++++++++++++----- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index cea9259f192f..bb796114c264 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -898,12 +898,11 @@ static int hns3_get_link_ksettings(struct net_device *netdev, } static int hns3_check_ksettings_param(const struct net_device *netdev, - const struct ethtool_link_ksettings *cmd) + const struct ethtool_link_ksettings *cmd, + u8 media_type) { struct hnae3_handle *handle = hns3_get_handle(netdev); const struct hnae3_ae_ops *ops = hns3_get_ops(handle); - u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN; - u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN; u32 lane_num; u8 autoneg; u32 speed; @@ -923,9 +922,6 @@ static int hns3_check_ksettings_param(const struct net_device *netdev, return 0; } - if (ops->get_media_type) - ops->get_media_type(handle, &media_type, &module_type); - if (cmd->base.duplex == DUPLEX_HALF && media_type != HNAE3_MEDIA_TYPE_COPPER) { netdev_err(netdev, @@ -950,6 +946,8 @@ static int hns3_set_link_ksettings(struct net_device *netdev, struct hnae3_handle *handle = hns3_get_handle(netdev); struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(handle); const struct hnae3_ae_ops *ops = hns3_get_ops(handle); + u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN; + u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN; int ret; /* Chip don't support this mode. */ @@ -965,22 +963,20 @@ static int hns3_set_link_ksettings(struct net_device *netdev, cmd->base.autoneg, cmd->base.speed, cmd->base.duplex, cmd->lanes); - /* Only support ksettings_set for netdev with phy attached for now */ - if (netdev->phydev) { - if (cmd->base.speed == SPEED_1000 && - cmd->base.autoneg == AUTONEG_DISABLE) - return -EINVAL; + if (!ops->get_media_type) + return -EOPNOTSUPP; + ops->get_media_type(handle, &media_type, &module_type); - return phy_ethtool_ksettings_set(netdev->phydev, cmd); - } else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) && - ops->set_phy_link_ksettings) { + if (media_type == HNAE3_MEDIA_TYPE_COPPER) { + if (!ops->set_phy_link_ksettings) + return -EOPNOTSUPP; return ops->set_phy_link_ksettings(handle, cmd); } if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) return -EOPNOTSUPP; - ret = hns3_check_ksettings_param(netdev, cmd); + ret = hns3_check_ksettings_param(netdev, cmd, media_type); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index a5029f957b09..ab48f1a4f850 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1607,8 +1607,11 @@ static int hclge_configure(struct hclge_dev *hdev) return ret; } hdev->hw.mac.req_speed = hdev->hw.mac.speed; - hdev->hw.mac.req_autoneg = AUTONEG_ENABLE; hdev->hw.mac.req_duplex = DUPLEX_FULL; + if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) + hdev->hw.mac.req_autoneg = AUTONEG_ENABLE; + else + hdev->hw.mac.req_autoneg = AUTONEG_DISABLE; hclge_parse_link_mode(hdev, cfg.speed_ability); @@ -2739,6 +2742,7 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + int ret; if (!hdev->hw.mac.support_autoneg) { if (enable) { @@ -2750,7 +2754,10 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable) } } - return hclge_set_autoneg_en(hdev, enable); + ret = hclge_set_autoneg_en(hdev, enable); + if (!ret) + hdev->hw.mac.req_autoneg = enable; + return ret; } static int hclge_get_autoneg(struct hnae3_handle *handle) @@ -3029,7 +3036,7 @@ static int hclge_mac_init(struct hclge_dev *hdev) hdev->hw.mac.duplex = HCLGE_MAC_FULL; if (hdev->hw.mac.support_autoneg) { - ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg); + ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.req_autoneg); if (ret) return ret; } @@ -3428,8 +3435,8 @@ static int hclge_get_phy_link_ksettings(struct hnae3_handle *handle, } static int -hclge_set_phy_link_ksettings(struct hnae3_handle *handle, - const struct ethtool_link_ksettings *cmd) +hclge_ethtool_ksettings_set(struct hnae3_handle *handle, + const struct ethtool_link_ksettings *cmd) { struct hclge_desc desc[HCLGE_PHY_LINK_SETTING_BD_NUM]; struct hclge_vport *vport = hclge_get_vport(handle); @@ -3439,12 +3446,6 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle, u32 advertising; int ret; - if (cmd->base.autoneg == AUTONEG_DISABLE && - ((cmd->base.speed != SPEED_100 && cmd->base.speed != SPEED_10) || - (cmd->base.duplex != DUPLEX_HALF && - cmd->base.duplex != DUPLEX_FULL))) - return -EINVAL; - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_PHY_LINK_KSETTING, false); desc[0].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); @@ -3464,6 +3465,32 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle, req1->master_slave_cfg = cmd->base.master_slave_cfg; ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_PHY_LINK_SETTING_BD_NUM); + + if (!ret) + linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising); + + return ret; +} + +static int +hclge_set_phy_link_ksettings(struct hnae3_handle *handle, + const struct ethtool_link_ksettings *cmd) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + int ret; + + if (cmd->base.autoneg == AUTONEG_DISABLE && + ((cmd->base.speed != SPEED_100 && cmd->base.speed != SPEED_10) || + (cmd->base.duplex != DUPLEX_HALF && + cmd->base.duplex != DUPLEX_FULL))) + return -EINVAL; + + if (hnae3_dev_phy_imp_supported(hdev)) + ret = hclge_ethtool_ksettings_set(handle, cmd); + else + ret = phy_ethtool_ksettings_set(handle->netdev->phydev, cmd); + if (ret) { dev_err(&hdev->pdev->dev, "failed to set phy link ksettings, ret = %d.\n", ret); @@ -3471,9 +3498,10 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle, } hdev->hw.mac.req_autoneg = cmd->base.autoneg; - hdev->hw.mac.req_speed = cmd->base.speed; - hdev->hw.mac.req_duplex = cmd->base.duplex; - linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising); + if (cmd->base.speed != SPEED_UNKNOWN) + hdev->hw.mac.req_speed = cmd->base.speed; + if (cmd->base.duplex != DUPLEX_UNKNOWN) + hdev->hw.mac.req_duplex = cmd->base.duplex; return 0; } -- Gitee From e5c346ec08ef1c015b0ed3de876b035ea6feb708 Mon Sep 17 00:00:00 2001 From: Hao Chen Date: Sun, 24 Oct 2021 16:08:32 +0800 Subject: [PATCH 08/12] net: hns3: replace magic numbers with macro for IPv4/v6 driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- Replace 4/6 with IP_VERSION_V4/6 to improve code readability. Signed-off-by: Hao Chen Signed-off-by: Jijie Shao Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index c0868305049a..2c6d72d0f83e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1356,7 +1356,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs, /* Software should clear the IPv4's checksum field when tso is * needed. */ - if (l3.v4->version == 4) + if (l3.v4->version == IP_VERSION_IPV4) l3.v4->check = 0; /* tunnel packet */ @@ -1371,7 +1371,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs, /* Software should clear the IPv4's checksum field when * tso is needed. */ - if (l3.v4->version == 4) + if (l3.v4->version == IP_VERSION_IPV4) l3.v4->check = 0; } @@ -1446,13 +1446,13 @@ static int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto, l3.hdr = skb_inner_network_header(skb); l4_hdr = skb_inner_transport_header(skb); - if (l3.v6->version == 6) { + if (l3.v6->version == IP_VERSION_IPV6) { exthdr = l3.hdr + sizeof(*l3.v6); l4_proto_tmp = l3.v6->nexthdr; if (l4_hdr != exthdr) ipv6_skip_exthdr(skb, exthdr - skb->data, &l4_proto_tmp, &frag_off); - } else if (l3.v4->version == 4) { + } else if (l3.v4->version == IP_VERSION_IPV4) { l4_proto_tmp = l3.v4->protocol; } @@ -1540,7 +1540,7 @@ static void hns3_set_outer_l2l3l4(struct sk_buff *skb, u8 ol4_proto, static void hns3_set_l3_type(struct sk_buff *skb, union l3_hdr_info l3, u32 *type_cs_vlan_tso) { - if (l3.v4->version == 4) { + if (l3.v4->version == IP_VERSION_IPV4) { hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S, HNS3_L3T_IPV4); @@ -1549,7 +1549,7 @@ static void hns3_set_l3_type(struct sk_buff *skb, union l3_hdr_info l3, */ if (skb_is_gso(skb)) hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3CS_B, 1); - } else if (l3.v6->version == 6) { + } else if (l3.v6->version == IP_VERSION_IPV6) { hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S, HNS3_L3T_IPV6); } -- Gitee From f40c18e9ce72b5c764fd31a889708b65d82e7b38 Mon Sep 17 00:00:00 2001 From: Shuaisong Yang Date: Thu, 7 Aug 2025 20:03:20 +0800 Subject: [PATCH 09/12] net: hns3: `req_autoneg` for fiber is initialized to `support_autoneg` instead of OFF. driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- When handling the issue of copper probabilistic failing to link up after reset, the parameter in `hclge_set_autoneg_en` was updated from `autoneg` to `req_autoneg`. And for fiber, `req_autoneg` is initialized to OFF. If fiber link up with autoneg ON, and the `hclge.ko` module is unloaded and reloaded, autoneg keeps ON and link up. The next reset will set autoneg to OFF based on `req_autoneg`, resulting in a failure to link up. In this patch, `req_autoneg` for fiber is initialized to `support_autoneg` instead of OFF. Consequently, both the initialization code for `req_autoneg` and the subsequent configuration setup must be moved after `hclge_update_port_info`. Fixes: 7459e2b2b2af ("net: hns3: use user configure after hardware reset when using kernel PHY.") Signed-off-by: Shuaisong Yang Signed-off-by: Donghua Huang --- .../hisilicon/hns3/hns3pf/hclge_main.c | 63 ++++++++++++++----- .../hisilicon/hns3/hns3pf/hclge_main.h | 3 +- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index ab48f1a4f850..1525f3c948cb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2712,7 +2712,7 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed, hdev->hw.mac.req_speed = (u32)speed; hdev->hw.mac.req_duplex = duplex; - + hdev->hw.mac.req_lane_num = lane_num; return 0; } @@ -3034,21 +3034,6 @@ static int hclge_mac_init(struct hclge_dev *hdev) if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) hdev->hw.mac.duplex = HCLGE_MAC_FULL; - - if (hdev->hw.mac.support_autoneg) { - ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.req_autoneg); - if (ret) - return ret; - } - - if (!hdev->hw.mac.autoneg) { - ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed, - hdev->hw.mac.req_duplex, - hdev->hw.mac.lane_num); - if (ret) - return ret; - } - mac->link = 0; if (mac->user_fec_mode & BIT(HNAE3_FEC_USER_DEF)) { @@ -12533,6 +12518,28 @@ static int hclge_set_wol(struct hnae3_handle *handle, return ret; } +static int hclge_set_autoneg_speed_dup(struct hclge_dev *hdev) +{ + int ret; + + if (hdev->hw.mac.support_autoneg) { + ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.req_autoneg); + if (ret) + return ret; + } + + if (!hdev->hw.mac.req_autoneg) { + ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed, + hdev->hw.mac.req_duplex, + hdev->hw.mac.req_lane_num); + if (ret) + return ret; + } + + return 0; +} + + static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) { struct pci_dev *pdev = ae_dev->pdev; @@ -12694,6 +12701,23 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) if (ret) goto err_ptp_uninit; + if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) + hdev->hw.mac.req_autoneg = AUTONEG_ENABLE; + else + hdev->hw.mac.req_autoneg = hdev->hw.mac.autoneg; + + /* When lane_num is 0, the firmware will automatically + * select the appropriate lane_num based on the speed. + */ + hdev->hw.mac.req_lane_num = 0; + + ret = hclge_set_autoneg_speed_dup(hdev); + if (ret) { + dev_err(&pdev->dev, + "failed to set autoneg speed duplex, ret = %d\n", ret); + goto err_ptp_uninit; + } + INIT_KFIFO(hdev->mac_tnl_log); hclge_dcb_ops_set(hdev); @@ -13026,6 +13050,13 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) return ret; } + ret = hclge_set_autoneg_speed_dup(hdev); + if (ret) { + dev_err(&pdev->dev, + "failed to set autoneg speed duplex, ret = %d\n", ret); + return ret; + } + ret = hclge_tp_port_init(hdev); if (ret) { dev_err(&pdev->dev, "failed to init tp port, ret = %d\n", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 4f723d7c037d..a4171f59105c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -286,9 +286,10 @@ struct hclge_mac { u8 req_autoneg; u8 duplex; u8 req_duplex; - u8 support_autoneg; + u8 support_autoneg; /* for non-copper port */ u8 speed_type; /* 0: sfp speed, 1: active speed */ u8 lane_num; + u8 req_lane_num; u32 speed; u32 req_speed; u32 max_speed; -- Gitee From eae5e382a9088c3221165e60f1881b9a7fc81c93 Mon Sep 17 00:00:00 2001 From: Hao Lan Date: Thu, 4 Jul 2024 22:45:48 +0800 Subject: [PATCH 10/12] net: hns3: fixed vf get max channels bug driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- Currently, the queried maximum of vf channels is the maximum of channels supported by each TC. However, the actual maximum of channels is the maximum of channels supported by the device. Fixes: 849e46077689 ("net: hns3: add ethtool_ops.get_channels support for VF") Signed-off-by: Jian Shen Signed-off-by: Hao Lan Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 7696b1963186..7ccf6625b27e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -3176,11 +3176,7 @@ static void hclgevf_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev) { - struct hnae3_handle *nic = &hdev->nic; - struct hnae3_knic_private_info *kinfo = &nic->kinfo; - - return min_t(u32, hdev->rss_size_max, - hdev->num_tqps / kinfo->tc_info.num_tc); + return min_t(u32, hdev->rss_size_max, hdev->num_tqps); } /** -- Gitee From fda8ccbb4b3ac30fcc6f5ddb9ea236bcaa9f518c Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Fri, 28 Feb 2025 16:15:37 +0800 Subject: [PATCH 11/12] net: hns3: avoid bitwise copy during RX buffer replace leg when page pool enabled driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- Bitwise copy of members of structures should be totally avoided. Refactoring of RX replace buffer leg and removing bitwise copy has improved performance by roughly 2Gbps in 1-core 1-queue performance benchmark test. Signed-off-by: Jian Shen Signed-off-by: Salil Mehta Signed-off-by: Hao Chen Signed-off-by: Donghua Huang --- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 2c6d72d0f83e..a62d34e4e21f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3652,11 +3652,12 @@ static int hns3_alloc_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb) { unsigned int order = hns3_page_order(ring); + u32 page_offset; struct page *p; if (ring->page_pool) { p = page_pool_dev_alloc_frag(ring->page_pool, - &cb->page_offset, + &page_offset, hns3_buf_size(ring)); if (unlikely(!p)) return -ENOMEM; @@ -3666,6 +3667,7 @@ static int hns3_alloc_buffer(struct hns3_enet_ring *ring, cb->dma = page_pool_get_dma_addr(p); cb->type = DESC_TYPE_PP_FRAG; cb->reuse_flag = 0; + cb->page_offset = page_offset; return 0; } @@ -3842,10 +3844,10 @@ static int hns3_alloc_ring_buffers(struct hns3_enet_ring *ring) static void hns3_replace_buffer(struct hns3_enet_ring *ring, int i, struct hns3_desc_cb *res_cb) { - if (!ring->page_pool) + if (!ring->page_pool) { hns3_unmap_buffer(ring, &ring->desc_cb[i]); - - ring->desc_cb[i] = *res_cb; + ring->desc_cb[i] = *res_cb; + } ring->desc_cb[i].refill = 1; ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma + ring->desc_cb[i].page_offset); @@ -3982,7 +3984,9 @@ static bool hns3_nic_alloc_rx_buffers(struct hns3_enet_ring *ring, hns3_reuse_buffer(ring, ring->next_to_use); } else { - ret = hns3_alloc_and_map_buffer(ring, &res_cbs); + if (!ring->page_pool) + desc_cb = &res_cbs; + ret = hns3_alloc_and_map_buffer(ring, desc_cb); if (ret) { hns3_ring_stats_update(ring, sw_err_cnt); @@ -3994,7 +3998,7 @@ static bool hns3_nic_alloc_rx_buffers(struct hns3_enet_ring *ring, HNS3_RING_RX_RING_HEAD_REG); return true; } - hns3_replace_buffer(ring, ring->next_to_use, &res_cbs); + hns3_replace_buffer(ring, ring->next_to_use, desc_cb); hns3_ring_stats_update(ring, non_reuse_pg); } @@ -5848,6 +5852,7 @@ static void hns3_clear_tx_ring(struct hns3_enet_ring *ring) static int hns3_clear_rx_ring(struct hns3_enet_ring *ring) { + struct hns3_desc_cb *desc_cb; struct hns3_desc_cb res_cbs; int ret; @@ -5856,8 +5861,11 @@ static int hns3_clear_rx_ring(struct hns3_enet_ring *ring) * freed in hns3_handle_rx_bd or will be freed by * stack, so we need to replace the buffer here. */ + desc_cb = &ring->desc_cb[ring->next_to_use]; if (!ring->desc_cb[ring->next_to_use].reuse_flag) { - ret = hns3_alloc_and_map_buffer(ring, &res_cbs); + if (!ring->page_pool) + desc_cb = &res_cbs; + ret = hns3_alloc_and_map_buffer(ring, desc_cb); if (ret) { hns3_ring_stats_update(ring, sw_err_cnt); /* if alloc new buffer fail, exit directly @@ -5868,7 +5876,7 @@ static int hns3_clear_rx_ring(struct hns3_enet_ring *ring) ret); return ret; } - hns3_replace_buffer(ring, ring->next_to_use, &res_cbs); + hns3_replace_buffer(ring, ring->next_to_use, desc_cb); } ring_ptr_move_fw(ring, next_to_use); } -- Gitee From 9c4fa555d76226566848b70f6cb5a0214626033c Mon Sep 17 00:00:00 2001 From: Jijie Shao Date: Sat, 30 Aug 2025 10:58:46 +0800 Subject: [PATCH 12/12] net: hns3: fix null pointer in debugfs issue driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ID39NM ---------------------------------------------------------------------- Currently, when debugfs and reset are executed concurrently, some resources are released during the reset process, which may cause debugfs to read null pointers or other anomalies. Therefore, in this patch, interception protection has been added to debugfs operations that are sensitive to reset. Signed-off-by: Jijie Shao Signed-off-by: Donghua Huang --- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 67 ++++++++++++++----- .../hisilicon/hns3/hns3pf/hclge_debugfs.c | 6 ++ 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index a8b6cd7d77d1..71a650f8e02e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -383,6 +383,15 @@ static const char * const dim_state_str[] = { "START", "IN_PROG", "APPLY" }; static const char * const dim_tune_stat_str[] = { "ON_TOP", "TIRED", "RIGHT", "LEFT" }; +static bool hns3_dbg_is_device_busy(struct hns3_nic_priv *priv) +{ + if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || + test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + return true; + + return false; +} + static void hns3_get_coal_info(struct hns3_enet_tqp_vector *tqp_vector, struct seq_file *s, int i, bool is_tx) { @@ -428,13 +437,16 @@ static void hns3_get_coal_info(struct hns3_enet_tqp_vector *tqp_vector, } } -static void hns3_dump_coal_info(struct seq_file *s, bool is_tx) +static int hns3_dump_coal_info(struct seq_file *s, bool is_tx) { struct hnae3_handle *h = hnae3_seq_file_to_handle(s); struct hns3_enet_tqp_vector *tqp_vector; struct hns3_nic_priv *priv = h->priv; unsigned int i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + seq_printf(s, "%s interrupt coalesce info:\n", is_tx ? "tx" : "rx"); seq_puts(s, "VEC_ID ALGO_STATE PROFILE_ID CQE_MODE TUNE_STATE "); @@ -442,18 +454,26 @@ static void hns3_dump_coal_info(struct seq_file *s, bool is_tx) seq_puts(s, "HW_GL HW_QL\n"); for (i = 0; i < priv->vector_num; i++) { + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + tqp_vector = &priv->tqp_vector[i]; hns3_get_coal_info(tqp_vector, s, i, is_tx); } + + return 0; } static int hns3_dbg_coal_info(struct seq_file *s, void *data) { - hns3_dump_coal_info(s, true); - seq_puts(s, "\n"); - hns3_dump_coal_info(s, false); + int ret; - return 0; + ret = hns3_dump_coal_info(s, true); + if (ret) + return ret; + + seq_puts(s, "\n"); + return hns3_dump_coal_info(s, false); } static void hns3_dump_rx_queue_info(struct hns3_enet_ring *ring, @@ -498,6 +518,9 @@ static int hns3_dbg_rx_queue_info(struct seq_file *s, void *data) struct hns3_enet_ring *ring; u32 i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + if (!priv->ring) { dev_err(&h->pdev->dev, "priv->ring is NULL\n"); return -EFAULT; @@ -511,8 +534,7 @@ static int hns3_dbg_rx_queue_info(struct seq_file *s, void *data) * to prevent reference to invalid memory. And need to ensure * that the following code is executed within 100ms. */ - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + if (hns3_dbg_is_device_busy(priv)) return -EPERM; ring = &priv->ring[(u32)(i + h->kinfo.num_tqps)]; @@ -563,6 +585,9 @@ static int hns3_dbg_tx_queue_info(struct seq_file *s, void *data) struct hns3_enet_ring *ring; u32 i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + if (!priv->ring) { dev_err(&h->pdev->dev, "priv->ring is NULL\n"); return -EFAULT; @@ -576,8 +601,7 @@ static int hns3_dbg_tx_queue_info(struct seq_file *s, void *data) * to prevent reference to invalid memory. And need to ensure * that the following code is executed within 100ms. */ - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + if (hns3_dbg_is_device_busy(priv)) return -EPERM; ring = &priv->ring[i]; @@ -596,6 +620,9 @@ static int hns3_dbg_queue_map(struct seq_file *s, void *data) if (!h->ae_algo->ops->get_global_queue_id) return -EOPNOTSUPP; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + seq_puts(s, "local_queue_id global_queue_id vector_id\n"); for (i = 0; i < h->kinfo.num_tqps; i++) { @@ -643,6 +670,9 @@ static int hns3_dbg_rx_bd_info(struct seq_file *s, void *private) struct hns3_desc *desc; unsigned int i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + if (data->qid >= h->kinfo.num_tqps) { dev_err(&h->pdev->dev, "queue%u is not in use\n", data->qid); return -EINVAL; @@ -655,8 +685,10 @@ static int hns3_dbg_rx_bd_info(struct seq_file *s, void *private) ring = &priv->ring[data->qid + data->handle->kinfo.num_tqps]; for (i = 0; i < ring->desc_num; i++) { - desc = &ring->desc[i]; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + desc = &ring->desc[i]; hns3_dump_rx_bd_info(priv, desc, s, i); } @@ -688,6 +720,9 @@ static int hns3_dbg_tx_bd_info(struct seq_file *s, void *private) struct hns3_desc *desc; unsigned int i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + if (data->qid >= h->kinfo.num_tqps) { dev_err(&h->pdev->dev, "queue%u is not in use\n", data->qid); return -EINVAL; @@ -700,8 +735,10 @@ static int hns3_dbg_tx_bd_info(struct seq_file *s, void *private) ring = &priv->ring[data->qid]; for (i = 0; i < ring->desc_num; i++) { - desc = &ring->desc[i]; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + desc = &ring->desc[i]; hns3_dump_tx_bd_info(desc, s, i); } @@ -804,9 +841,8 @@ static int hns3_dbg_page_pool_info(struct seq_file *s, void *data) seq_puts(s, "POOL_SIZE(PAGE_NUM) ORDER NUMA_ID MAX_LEN\n"); for (i = 0; i < h->kinfo.num_tqps; i++) { - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) - return -EPERM; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; ring = &priv->ring[(u32)(i + h->kinfo.num_tqps)]; hns3_dump_page_pool_info(ring, s, i); @@ -821,8 +857,7 @@ static int hns3_dbg_bd_info_show(struct seq_file *s, void *private) struct hnae3_handle *h = data->handle; struct hns3_nic_priv *priv = h->priv; - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + if (hns3_dbg_is_device_busy(priv)) return -EBUSY; if (data->cmd == HNAE3_DBG_CMD_TX_BD) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 008c8a5b6158..ae82bd55752a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -2542,6 +2542,9 @@ static int hclge_dbg_dump_umv_info(struct seq_file *s, void *data) struct hclge_vport *vport; u8 i; + if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) + return -EBUSY; + seq_printf(s, "num_alloc_vport : %u\n", hdev->num_alloc_vport); seq_printf(s, "max_umv_size : %u\n", hdev->max_umv_size); seq_printf(s, "wanted_umv_size : %u\n", hdev->wanted_umv_size); @@ -2752,6 +2755,9 @@ static int hclge_dbg_dump_vlan_offload_config(struct hclge_dev *hdev, int ret; u8 i; + if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) + return -EBUSY; + seq_puts(s, "FUNC_ID PVID ACCEPT_TAG1 ACCEPT_TAG2 ACCEPT_UNTAG1 "); seq_puts(s, "ACCEPT_UNTAG2 INSERT_TAG1 INSERT_TAG2 SHIFT_TAG "); seq_puts(s, "STRIP_TAG1 STRIP_TAG2 DROP_TAG1 DROP_TAG2 "); -- Gitee