From nobody Tue Sep 9 21:30:26 2025 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F13F326738D; Fri, 5 Sep 2025 08:29:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060943; cv=none; b=Q1efpfnrQP58eqUP5RbjDHvWrcteIgoIG/0mkkedGxdDgMx5zLqw+UaCR0mxB/ShTCUHF88loKxYpTvf+Iuqa4Gh02Qzckg/QUsXGtzoEvVuEytWD4L4jJBByHz12t7ePudJlguqy+kx8oDdxKGolDbVeT5xBX4yVEb3ROIHswQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060943; c=relaxed/simple; bh=ayaGakuu4DYw+n1GH+wLESSt2u4fIFjR4mJpSwpbOEM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NkemaVE5J9fWrZrcLqAHdRbUH35sZ6GrVXh/hNUvhiL/fPfp27qqgmPEaYk32cB2C3RNB0JiSEGi/JsUdwe9j+yxqzn+965ypXxRfm7qLopV8zGdNfCVrvmm2lSRqsgtY2D7FTd1PzkE+WSpPxjzB4XsDq2SSevCEtazaBwdA7g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.105]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4cJ8X60226zQlL1; Fri, 5 Sep 2025 16:24:22 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 819FE140147; Fri, 5 Sep 2025 16:28:58 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:28:56 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 01/14] hinic3: HW initialization Date: Fri, 5 Sep 2025 16:28:35 +0800 Message-ID: <3cdc022cf46e8b7ce101c2df84100ce9a8f69552.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Add the hardware resource data structures, functions for HW initialization, configuration and releasement. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../net/ethernet/huawei/hinic3/hinic3_hwdev.c | 52 +++- .../net/ethernet/huawei/hinic3/hinic3_hwif.c | 243 ++++++++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_hwif.h | 13 + .../net/ethernet/huawei/hinic3/hinic3_lld.c | 3 +- .../huawei/hinic3/hinic3_pci_id_tbl.h | 9 + 5 files changed, 316 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.c index 6e8788a64925..09e8b0dce7b3 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -7,15 +7,61 @@ #include "hinic3_mbox.h" #include "hinic3_mgmt.h" =20 +#define HINIC3_HWDEV_WQ_NAME "hinic3_hardware" +#define HINIC3_WQ_MAX_REQ 10 + +enum hinic3_hwdev_init_state { + HINIC3_HWDEV_MBOX_INITED =3D 2, + HINIC3_HWDEV_CMDQ_INITED =3D 3, +}; + int hinic3_init_hwdev(struct pci_dev *pdev) { - /* Completed by later submission due to LoC limit. */ - return -EFAULT; + struct hinic3_pcidev *pci_adapter =3D pci_get_drvdata(pdev); + struct hinic3_hwdev *hwdev; + int err; + + hwdev =3D kzalloc(sizeof(*hwdev), GFP_KERNEL); + if (!hwdev) + return -ENOMEM; + + pci_adapter->hwdev =3D hwdev; + hwdev->adapter =3D pci_adapter; + hwdev->pdev =3D pci_adapter->pdev; + hwdev->dev =3D &pci_adapter->pdev->dev; + hwdev->func_state =3D 0; + spin_lock_init(&hwdev->channel_lock); + + err =3D hinic3_init_hwif(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init hwif\n"); + goto err_free_hwdev; + } + + hwdev->workq =3D alloc_workqueue(HINIC3_HWDEV_WQ_NAME, WQ_MEM_RECLAIM, + HINIC3_WQ_MAX_REQ); + if (!hwdev->workq) { + dev_err(hwdev->dev, "Failed to alloc hardware workq\n"); + err =3D -ENOMEM; + goto err_free_hwif; + } + + return 0; + +err_free_hwif: + hinic3_free_hwif(hwdev); +err_free_hwdev: + pci_adapter->hwdev =3D NULL; + kfree(hwdev); + + return err; } =20 void hinic3_free_hwdev(struct hinic3_hwdev *hwdev) { - /* Completed by later submission due to LoC limit. */ + destroy_workqueue(hwdev->workq); + hinic3_free_hwif(hwdev); + kfree(hwdev); } =20 void hinic3_set_api_stop(struct hinic3_hwdev *hwdev) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_hwif.c index d4af376b7f35..90b8e211587f 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c @@ -10,6 +10,10 @@ #include "hinic3_hwdev.h" #include "hinic3_hwif.h" =20 +#define HINIC3_HWIF_READY_TIMEOUT 10000 +#define HINIC3_DB_AND_OUTBOUND_EN_TIMEOUT 60000 +#define HINIC3_PCIE_LINK_DOWN 0xFFFFFFFF + /* config BAR4/5 4MB, DB & DWQE both 2MB */ #define HINIC3_DB_DWQE_SIZE 0x00400000 =20 @@ -18,6 +22,41 @@ #define HINIC3_DWQE_OFFSET 0x00000800 #define HINIC3_DB_MAX_AREAS (HINIC3_DB_DWQE_SIZE / HINIC3_DB_PAGE_SIZE) =20 +#define HINIC3_MAX_MSIX_ENTRY 2048 + +#define HINIC3_AF0_FUNC_GLOBAL_IDX_MASK GENMASK(11, 0) +#define HINIC3_AF0_P2P_IDX_MASK GENMASK(16, 12) +#define HINIC3_AF0_PCI_INTF_IDX_MASK GENMASK(19, 17) +#define HINIC3_AF0_FUNC_TYPE_MASK BIT(28) +#define HINIC3_AF0_GET(val, member) \ + FIELD_GET(HINIC3_AF0_##member##_MASK, val) + +#define HINIC3_AF1_AEQS_PER_FUNC_MASK GENMASK(9, 8) +#define HINIC3_AF1_MGMT_INIT_STATUS_MASK BIT(30) +#define HINIC3_AF1_GET(val, member) \ + FIELD_GET(HINIC3_AF1_##member##_MASK, val) + +#define HINIC3_AF2_CEQS_PER_FUNC_MASK GENMASK(8, 0) +#define HINIC3_AF2_IRQS_PER_FUNC_MASK GENMASK(26, 16) +#define HINIC3_AF2_GET(val, member) \ + FIELD_GET(HINIC3_AF2_##member##_MASK, val) + +#define HINIC3_AF4_DOORBELL_CTRL_MASK BIT(0) +#define HINIC3_AF4_GET(val, member) \ + FIELD_GET(HINIC3_AF4_##member##_MASK, val) +#define HINIC3_AF4_SET(val, member) \ + FIELD_PREP(HINIC3_AF4_##member##_MASK, val) + +#define HINIC3_AF5_OUTBOUND_CTRL_MASK BIT(0) +#define HINIC3_AF5_GET(val, member) \ + FIELD_GET(HINIC3_AF5_##member##_MASK, val) + +#define HINIC3_AF6_PF_STATUS_MASK GENMASK(15, 0) +#define HINIC3_AF6_FUNC_MAX_SQ_MASK GENMASK(31, 23) +#define HINIC3_AF6_MSIX_FLEX_EN_MASK BIT(22) +#define HINIC3_AF6_GET(val, member) \ + FIELD_GET(HINIC3_AF6_##member##_MASK, val) + #define HINIC3_GET_REG_ADDR(reg) ((reg) & (HINIC3_REGS_FLAG_MASK)) =20 static void __iomem *hinic3_reg_addr(struct hinic3_hwif *hwif, u32 reg) @@ -39,6 +78,116 @@ void hinic3_hwif_write_reg(struct hinic3_hwif *hwif, u3= 2 reg, u32 val) iowrite32be(val, addr); } =20 +static enum hinic3_wait_return check_hwif_ready_handler(void *priv_data) +{ + struct hinic3_hwdev *hwdev =3D priv_data; + u32 attr1; + + attr1 =3D hinic3_hwif_read_reg(hwdev->hwif, HINIC3_CSR_FUNC_ATTR1_ADDR); + + return HINIC3_AF1_GET(attr1, MGMT_INIT_STATUS) ? + HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING; +} + +static int wait_hwif_ready(struct hinic3_hwdev *hwdev) +{ + return hinic3_wait_for_timeout(hwdev, check_hwif_ready_handler, + HINIC3_HWIF_READY_TIMEOUT, + USEC_PER_MSEC); +} + +/* Set attr struct from HW attr values. */ +static void set_hwif_attr(struct hinic3_func_attr *attr, u32 attr0, u32 at= tr1, + u32 attr2, u32 attr3, u32 attr6) +{ + attr->func_global_idx =3D HINIC3_AF0_GET(attr0, FUNC_GLOBAL_IDX); + attr->port_to_port_idx =3D HINIC3_AF0_GET(attr0, P2P_IDX); + attr->pci_intf_idx =3D HINIC3_AF0_GET(attr0, PCI_INTF_IDX); + attr->func_type =3D HINIC3_AF0_GET(attr0, FUNC_TYPE); + + attr->num_aeqs =3D BIT(HINIC3_AF1_GET(attr1, AEQS_PER_FUNC)); + attr->num_ceqs =3D HINIC3_AF2_GET(attr2, CEQS_PER_FUNC); + attr->num_irqs =3D HINIC3_AF2_GET(attr2, IRQS_PER_FUNC); + if (attr->num_irqs > HINIC3_MAX_MSIX_ENTRY) + attr->num_irqs =3D HINIC3_MAX_MSIX_ENTRY; + + attr->num_sq =3D HINIC3_AF6_GET(attr6, FUNC_MAX_SQ); + attr->msix_flex_en =3D HINIC3_AF6_GET(attr6, MSIX_FLEX_EN); +} + +/* Read attributes from HW and set attribute struct. */ +static int init_hwif_attr(struct hinic3_hwdev *hwdev) +{ + u32 attr0, attr1, attr2, attr3, attr6; + struct hinic3_hwif *hwif; + + hwif =3D hwdev->hwif; + attr0 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR0_ADDR); + if (attr0 =3D=3D HINIC3_PCIE_LINK_DOWN) + return -EFAULT; + + attr1 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR1_ADDR); + if (attr1 =3D=3D HINIC3_PCIE_LINK_DOWN) + return -EFAULT; + + attr2 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR2_ADDR); + if (attr2 =3D=3D HINIC3_PCIE_LINK_DOWN) + return -EFAULT; + + attr3 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR3_ADDR); + if (attr3 =3D=3D HINIC3_PCIE_LINK_DOWN) + return -EFAULT; + + attr6 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR6_ADDR); + if (attr6 =3D=3D HINIC3_PCIE_LINK_DOWN) + return -EFAULT; + + set_hwif_attr(&hwif->attr, attr0, attr1, attr2, attr3, attr6); + + return 0; +} + +static enum hinic3_doorbell_ctrl hinic3_get_doorbell_ctrl_status(struct hi= nic3_hwif *hwif) +{ + u32 attr4 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR4_ADDR); + + return HINIC3_AF4_GET(attr4, DOORBELL_CTRL); +} + +static enum hinic3_outbound_ctrl hinic3_get_outbound_ctrl_status(struct hi= nic3_hwif *hwif) +{ + u32 attr5 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR5_ADDR); + + return HINIC3_AF5_GET(attr5, OUTBOUND_CTRL); +} + +static int db_area_idx_init(struct hinic3_hwif *hwif, u64 db_base_phy, + u8 __iomem *db_base, u64 db_dwqe_len) +{ + struct hinic3_db_area *db_area =3D &hwif->db_area; + u32 db_max_areas; + + hwif->db_base_phy =3D db_base_phy; + hwif->db_base =3D db_base; + hwif->db_dwqe_len =3D db_dwqe_len; + + db_max_areas =3D db_dwqe_len > HINIC3_DB_DWQE_SIZE ? + HINIC3_DB_MAX_AREAS : db_dwqe_len / HINIC3_DB_PAGE_SIZE; + db_area->db_bitmap_array =3D bitmap_zalloc(db_max_areas, GFP_KERNEL); + if (!db_area->db_bitmap_array) + return -ENOMEM; + + db_area->db_max_areas =3D db_max_areas; + spin_lock_init(&db_area->idx_lock); + + return 0; +} + +static void db_area_idx_free(struct hinic3_db_area *db_area) +{ + bitmap_free(db_area->db_bitmap_array); +} + static int get_db_idx(struct hinic3_hwif *hwif, u32 *idx) { struct hinic3_db_area *db_area =3D &hwif->db_area; @@ -125,6 +274,15 @@ void hinic3_set_msix_state(struct hinic3_hwdev *hwdev,= u16 msix_idx, hinic3_hwif_write_reg(hwif, addr, mask_bits); } =20 +static void disable_all_msix(struct hinic3_hwdev *hwdev) +{ + u16 num_irqs =3D hwdev->hwif->attr.num_irqs; + u16 i; + + for (i =3D 0; i < num_irqs; i++) + hinic3_set_msix_state(hwdev, i, HINIC3_MSIX_DISABLE); +} + void hinic3_msix_intr_clear_resend_bit(struct hinic3_hwdev *hwdev, u16 msi= x_idx, u8 clear_resend_en) { @@ -161,6 +319,91 @@ void hinic3_set_msix_auto_mask_state(struct hinic3_hwd= ev *hwdev, u16 msix_idx, hinic3_hwif_write_reg(hwif, addr, mask_bits); } =20 +static enum hinic3_wait_return check_db_outbound_enable_handler(void *priv= _data) +{ + enum hinic3_outbound_ctrl outbound_ctrl; + struct hinic3_hwif *hwif =3D priv_data; + enum hinic3_doorbell_ctrl db_ctrl; + + db_ctrl =3D hinic3_get_doorbell_ctrl_status(hwif); + outbound_ctrl =3D hinic3_get_outbound_ctrl_status(hwif); + if (outbound_ctrl =3D=3D ENABLE_OUTBOUND && db_ctrl =3D=3D ENABLE_DOORBEL= L) + return HINIC3_WAIT_PROCESS_CPL; + + return HINIC3_WAIT_PROCESS_WAITING; +} + +static int wait_until_doorbell_and_outbound_enabled(struct hinic3_hwif *hw= if) +{ + return hinic3_wait_for_timeout(hwif, check_db_outbound_enable_handler, + HINIC3_DB_AND_OUTBOUND_EN_TIMEOUT, + USEC_PER_MSEC); +} + +int hinic3_init_hwif(struct hinic3_hwdev *hwdev) +{ + struct hinic3_pcidev *pci_adapter =3D hwdev->adapter; + struct hinic3_hwif *hwif; + u32 attr1, attr4, attr5; + int err; + + hwif =3D kzalloc(sizeof(*hwif), GFP_KERNEL); + if (!hwif) + return -ENOMEM; + + hwdev->hwif =3D hwif; + hwif->cfg_regs_base =3D (u8 __iomem *)pci_adapter->cfg_reg_base + + HINIC3_VF_CFG_REG_OFFSET; + + err =3D db_area_idx_init(hwif, pci_adapter->db_base_phy, + pci_adapter->db_base, + pci_adapter->db_dwqe_len); + if (err) { + dev_err(hwdev->dev, "Failed to init db area.\n"); + goto err_free_hwif; + } + + err =3D wait_hwif_ready(hwdev); + if (err) { + attr1 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR1_ADDR); + dev_err(hwdev->dev, "Chip status is not ready, attr1:0x%x\n", + attr1); + goto err_free_db_area_idx; + } + + err =3D init_hwif_attr(hwdev); + if (err) { + dev_err(hwdev->dev, "Init hwif attr failed\n"); + goto err_free_db_area_idx; + } + + err =3D wait_until_doorbell_and_outbound_enabled(hwif); + if (err) { + attr4 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR4_ADDR); + attr5 =3D hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR5_ADDR); + dev_err(hwdev->dev, "HW doorbell/outbound is disabled, attr4 0x%x attr5 = 0x%x\n", + attr4, attr5); + goto err_free_db_area_idx; + } + + disable_all_msix(hwdev); + + return 0; + +err_free_db_area_idx: + db_area_idx_free(&hwif->db_area); +err_free_hwif: + kfree(hwif); + + return err; +} + +void hinic3_free_hwif(struct hinic3_hwdev *hwdev) +{ + db_area_idx_free(&hwdev->hwif->db_area); + kfree(hwdev->hwif); +} + u16 hinic3_global_func_id(struct hinic3_hwdev *hwdev) { return hwdev->hwif->attr.func_global_idx; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.h b/drivers/net= /ethernet/huawei/hinic3/hinic3_hwif.h index 29dd86eb458a..48e43bfdbfbe 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.h @@ -45,6 +45,16 @@ struct hinic3_hwif { struct hinic3_func_attr attr; }; =20 +enum hinic3_outbound_ctrl { + ENABLE_OUTBOUND =3D 0x0, + DISABLE_OUTBOUND =3D 0x1, +}; + +enum hinic3_doorbell_ctrl { + ENABLE_DOORBELL =3D 0, + DISABLE_DOORBELL =3D 1, +}; + enum hinic3_msix_state { HINIC3_MSIX_ENABLE, HINIC3_MSIX_DISABLE, @@ -62,6 +72,9 @@ int hinic3_alloc_db_addr(struct hinic3_hwdev *hwdev, void= __iomem **db_base, void __iomem **dwqe_base); void hinic3_free_db_addr(struct hinic3_hwdev *hwdev, const u8 __iomem *db_= base); =20 +int hinic3_init_hwif(struct hinic3_hwdev *hwdev); +void hinic3_free_hwif(struct hinic3_hwdev *hwdev); + void hinic3_set_msix_state(struct hinic3_hwdev *hwdev, u16 msix_idx, enum hinic3_msix_state flag); void hinic3_msix_intr_clear_resend_bit(struct hinic3_hwdev *hwdev, u16 msi= x_idx, diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_lld.c index 4827326e6a59..9f3d6af71cc8 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c @@ -8,6 +8,7 @@ #include "hinic3_hwdev.h" #include "hinic3_lld.h" #include "hinic3_mgmt.h" +#include "hinic3_pci_id_tbl.h" =20 #define HINIC3_VF_PCI_CFG_REG_BAR 0 #define HINIC3_PCI_INTR_REG_BAR 2 @@ -377,7 +378,7 @@ static void hinic3_remove(struct pci_dev *pdev) } =20 static const struct pci_device_id hinic3_pci_table[] =3D { - /* Completed by later submission due to LoC limit. */ + {PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_VF), 0}, {0, 0} =20 }; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h b/drive= rs/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h new file mode 100644 index 000000000000..86c88d0bb4bd --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. = */ + +#ifndef _HINIC3_PCI_ID_TBL_H_ +#define _HINIC3_PCI_ID_TBL_H_ + +#define PCI_DEV_ID_HINIC3_VF 0x375F + +#endif --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34A2D30AD0D; Fri, 5 Sep 2025 08:29:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.190 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060952; cv=none; b=Q23penrrS+NsBFPHSolIuD5uqcMu+LhrE9Ir6I72MJ5lGVI795Sv/GouDx4yQlQRzvd0ZhlumMpWR/87hZJMmD0HYAAMQzI55xX4nGoM2ZOURuPA8xrViA8xnw4Xs71JEoKCvi5LaMIGgxPVDgJxX7IJAGADSxN6x8YdahohW8c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060952; c=relaxed/simple; bh=y3GLFD6cVXQc/Gkt2yfxxAkJvYmpbOPjoB/5gi1C08E=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bRhzn0WSW1RGWncIh9QIir20utuQPu20TKBWgJYHITQc4kDm5uFxdQdQkGncOjSE/iDpKIhz4XtJ5V97nAC1BcZOngOy+6CU7WRyAk9f+RUygUq/X0QIow/Gi6RkIK675276uNjCJLLgT8M5vZl6AVShVTaz5VmCoOY2ongEheg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.190 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.162.112]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4cJ8XG6X9Mz2Cg1j; Fri, 5 Sep 2025 16:24:30 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id D009514022E; Fri, 5 Sep 2025 16:29:00 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:28:59 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 02/14] hinic3: HW management interfaces Date: Fri, 5 Sep 2025 16:28:36 +0800 Message-ID: <603ae8e87791ac0f0fab819f2acf4c58a509bb2d.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Initialize hardware management config of irq, aeq and ceq. These will send hardware messages to driver. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- drivers/net/ethernet/huawei/hinic3/Makefile | 1 + .../ethernet/huawei/hinic3/hinic3_hw_cfg.c | 102 ++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_hw_cfg.h | 3 + .../net/ethernet/huawei/hinic3/hinic3_hwdev.c | 10 ++ .../net/ethernet/huawei/hinic3/hinic3_hwif.c | 12 +++ .../net/ethernet/huawei/hinic3/hinic3_lld.c | 1 + .../net/ethernet/huawei/hinic3/hinic3_mgmt.c | 21 ++++ .../net/ethernet/huawei/hinic3/hinic3_mgmt.h | 2 + 8 files changed, 152 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/Makefile b/drivers/net/ethe= rnet/huawei/hinic3/Makefile index 2a0ed8e2c63e..a9f055cfef52 100644 --- a/drivers/net/ethernet/huawei/hinic3/Makefile +++ b/drivers/net/ethernet/huawei/hinic3/Makefile @@ -14,6 +14,7 @@ hinic3-objs :=3D hinic3_cmdq.o \ hinic3_lld.o \ hinic3_main.o \ hinic3_mbox.o \ + hinic3_mgmt.o \ hinic3_netdev_ops.o \ hinic3_nic_cfg.o \ hinic3_nic_io.o \ diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c b/drivers/n= et/ethernet/huawei/hinic3/hinic3_hw_cfg.c index 0599fc4f3fb0..8db5e2c9ff10 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c @@ -8,6 +8,108 @@ #include "hinic3_hwif.h" #include "hinic3_mbox.h" =20 +static int hinic3_init_irq_info(struct hinic3_hwdev *hwdev) +{ + struct hinic3_cfg_mgmt_info *cfg_mgmt =3D hwdev->cfg_mgmt; + struct hinic3_hwif *hwif =3D hwdev->hwif; + u16 intr_num =3D hwif->attr.num_irqs; + struct hinic3_irq_info *irq_info; + u16 intr_needed; + + intr_needed =3D hwif->attr.msix_flex_en ? (hwif->attr.num_aeqs + + hwif->attr.num_ceqs + hwif->attr.num_sq) : intr_num; + if (intr_needed > intr_num) { + dev_warn(hwdev->dev, "Irq num cfg %d is less than the needed irq num %d = msix_flex_en %d\n", + intr_num, intr_needed, hwdev->hwif->attr.msix_flex_en); + intr_needed =3D intr_num; + } + + irq_info =3D &cfg_mgmt->irq_info; + irq_info->irq =3D kcalloc(intr_num, sizeof(struct hinic3_irq), + GFP_KERNEL); + if (!irq_info->irq) + return -ENOMEM; + + irq_info->num_irq_hw =3D intr_needed; + mutex_init(&irq_info->irq_mutex); + + return 0; +} + +static int hinic3_init_irq_alloc_info(struct hinic3_hwdev *hwdev) +{ + struct hinic3_cfg_mgmt_info *cfg_mgmt =3D hwdev->cfg_mgmt; + struct hinic3_irq *irq =3D cfg_mgmt->irq_info.irq; + u16 nreq =3D cfg_mgmt->irq_info.num_irq_hw; + struct pci_dev *pdev =3D hwdev->pdev; + int actual_irq; + u16 i; + + actual_irq =3D pci_alloc_irq_vectors(pdev, 2, nreq, PCI_IRQ_MSIX); + if (actual_irq < 0) { + dev_err(hwdev->dev, "Alloc msix entries with threshold 2 failed. actual_= irq: %d\n", + actual_irq); + return -ENOMEM; + } + + nreq =3D actual_irq; + cfg_mgmt->irq_info.num_irq =3D nreq; + + for (i =3D 0; i < nreq; ++i) { + irq[i].msix_entry_idx =3D i; + irq[i].irq_id =3D pci_irq_vector(pdev, i); + irq[i].allocated =3D false; + } + + return 0; +} + +int hinic3_init_cfg_mgmt(struct hinic3_hwdev *hwdev) +{ + struct hinic3_cfg_mgmt_info *cfg_mgmt; + int err; + + cfg_mgmt =3D kzalloc(sizeof(*cfg_mgmt), GFP_KERNEL); + if (!cfg_mgmt) + return -ENOMEM; + + hwdev->cfg_mgmt =3D cfg_mgmt; + + err =3D hinic3_init_irq_info(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init hinic3_irq_mgmt_info, err: %d\n", + err); + goto err_free_cfg_mgmt; + } + + err =3D hinic3_init_irq_alloc_info(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init hinic3_irq_info, err: %d\n", + err); + goto err_free_irq_info; + } + + return 0; + +err_free_irq_info: + kfree(cfg_mgmt->irq_info.irq); + cfg_mgmt->irq_info.irq =3D NULL; +err_free_cfg_mgmt: + kfree(cfg_mgmt); + + return err; +} + +void hinic3_free_cfg_mgmt(struct hinic3_hwdev *hwdev) +{ + struct hinic3_cfg_mgmt_info *cfg_mgmt =3D hwdev->cfg_mgmt; + + pci_free_irq_vectors(hwdev->pdev); + kfree(cfg_mgmt->irq_info.irq); + cfg_mgmt->irq_info.irq =3D NULL; + kfree(cfg_mgmt); +} + int hinic3_alloc_irqs(struct hinic3_hwdev *hwdev, u16 num, struct msix_entry *alloc_arr, u16 *act_num) { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_hw_cfg.h index e017b1ae9f05..5978cbd56fb2 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h @@ -42,6 +42,9 @@ struct hinic3_cfg_mgmt_info { struct hinic3_dev_cap cap; }; =20 +int hinic3_init_cfg_mgmt(struct hinic3_hwdev *hwdev); +void hinic3_free_cfg_mgmt(struct hinic3_hwdev *hwdev); + int hinic3_alloc_irqs(struct hinic3_hwdev *hwdev, u16 num, struct msix_entry *alloc_arr, u16 *act_num); void hinic3_free_irq(struct hinic3_hwdev *hwdev, u32 irq_id); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.c index 09e8b0dce7b3..d941b365b574 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. =20 +#include "hinic3_eqs.h" #include "hinic3_hw_comm.h" #include "hinic3_hwdev.h" #include "hinic3_hwif.h" @@ -46,8 +47,16 @@ int hinic3_init_hwdev(struct pci_dev *pdev) goto err_free_hwif; } =20 + err =3D hinic3_init_cfg_mgmt(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init config mgmt\n"); + goto err_destroy_workqueue; + } + return 0; =20 +err_destroy_workqueue: + destroy_workqueue(hwdev->workq); err_free_hwif: hinic3_free_hwif(hwdev); err_free_hwdev: @@ -59,6 +68,7 @@ int hinic3_init_hwdev(struct pci_dev *pdev) =20 void hinic3_free_hwdev(struct hinic3_hwdev *hwdev) { + hinic3_free_cfg_mgmt(hwdev); destroy_workqueue(hwdev->workq); hinic3_free_hwif(hwdev); kfree(hwdev); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_hwif.c index 90b8e211587f..f07bcab51ba5 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c @@ -144,6 +144,18 @@ static int init_hwif_attr(struct hinic3_hwdev *hwdev) =20 set_hwif_attr(&hwif->attr, attr0, attr1, attr2, attr3, attr6); =20 + if (!hwif->attr.num_ceqs) { + dev_err(hwdev->dev, "Ceq num cfg in fw is zero\n"); + return -EFAULT; + } + + if (!hwif->attr.num_irqs) { + dev_err(hwdev->dev, + "Irq num cfg in fw is zero, msix_flex_en %d\n", + hwif->attr.msix_flex_en); + return -EFAULT; + } + return 0; } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_lld.c index 9f3d6af71cc8..10477fb9cc34 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c @@ -308,6 +308,7 @@ static void hinic3_func_uninit(struct pci_dev *pdev) { struct hinic3_pcidev *pci_adapter =3D pci_get_drvdata(pdev); =20 + hinic3_flush_mgmt_workq(pci_adapter->hwdev); hinic3_detach_aux_devices(pci_adapter->hwdev); hinic3_free_hwdev(pci_adapter->hwdev); } diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_mgmt.c new file mode 100644 index 000000000000..c38d10cd7fac --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + +#include "hinic3_eqs.h" +#include "hinic3_hwdev.h" +#include "hinic3_mbox.h" +#include "hinic3_mgmt.h" + +void hinic3_flush_mgmt_workq(struct hinic3_hwdev *hwdev) +{ + if (hwdev->aeqs) + flush_workqueue(hwdev->aeqs->workq); +} + +void hinic3_mgmt_msg_aeqe_handler(struct hinic3_hwdev *hwdev, u8 *header, + u8 size) +{ + if (MBOX_MSG_HEADER_GET(*(__force __le64 *)header, SOURCE) =3D=3D + MBOX_MSG_FROM_MBOX) + hinic3_mbox_func_aeqe_handler(hwdev, header, size); +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.h b/drivers/net= /ethernet/huawei/hinic3/hinic3_mgmt.h index 4edabeb32112..bbef3b32a6ec 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.h @@ -9,5 +9,7 @@ struct hinic3_hwdev; =20 void hinic3_flush_mgmt_workq(struct hinic3_hwdev *hwdev); +void hinic3_mgmt_msg_aeqe_handler(struct hinic3_hwdev *hwdev, + u8 *header, u8 size); =20 #endif --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga03-in.huawei.com (szxga03-in.huawei.com [45.249.212.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 32CA73093C3; Fri, 5 Sep 2025 08:29:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.189 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060948; cv=none; b=BAafF126xM6fdNG7B2PUfymfDRp9fz7+wFrM1GwiVMR4o9w/7xkoG3r/pgLA97Ey0akoBNniC1f8hZbm8qebQPVa5RNBKvCIdRsdy7PuAt6n4yvkGQdZZC08a+IlgghZUUPCvXt5PciRNjFXoL3s4WZsXP6OJiEH68XIigixK8g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060948; c=relaxed/simple; bh=vG5vs1WRAmy4rKkXxCR+tYRzCMrwd6FJ/0hLvVBsnz8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=T9vHw9Jzgm4xNGsJKFBFNX3u4tBIm1x8UDlHWvks/xjvNo3KaByjTEIdccN6BPflhc5SOhv93cl/5ygdp1Q1X/7h4jMQKtCleC3z0HHJcI+Jr4+zeqQaj58qzJqFulWrWnK1me47y6meOVcWeNVU/uQT/FssnNvcVOajMXS1uq8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.189 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.174]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4cJ8XK0fTnzPtPB; Fri, 5 Sep 2025 16:24:33 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 364DE140278; Fri, 5 Sep 2025 16:29:03 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:01 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 03/14] hinic3: HW common function initialization Date: Fri, 5 Sep 2025 16:28:37 +0800 Message-ID: <846ca641a5a4d6b0c66cf44a2e5c55713449aa5d.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Add initialization for data structures and functions(cmdq ceq mbox ceq) that interact with hardware. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_hw_comm.c | 174 +++++++ .../ethernet/huawei/hinic3/hinic3_hw_comm.h | 17 + .../ethernet/huawei/hinic3/hinic3_hw_intf.h | 67 +++ .../net/ethernet/huawei/hinic3/hinic3_hwdev.c | 457 +++++++++++++++++- 4 files changed, 714 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.c index 7adcdd569c7b..b016806c7f67 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c @@ -3,6 +3,7 @@ =20 #include =20 +#include "hinic3_cmdq.h" #include "hinic3_hw_comm.h" #include "hinic3_hwdev.h" #include "hinic3_hwif.h" @@ -61,3 +62,176 @@ int hinic3_func_reset(struct hinic3_hwdev *hwdev, u16 f= unc_id, u64 reset_flag) =20 return 0; } + +static int hinic3_comm_features_nego(struct hinic3_hwdev *hwdev, u8 opcode, + u64 *s_feature, u16 size) +{ + struct comm_cmd_feature_nego feature_nego =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + feature_nego.func_id =3D hinic3_global_func_id(hwdev); + feature_nego.opcode =3D opcode; + if (opcode =3D=3D MGMT_MSG_CMD_OP_SET) + memcpy(feature_nego.s_feature, s_feature, (size * sizeof(u64))); + + mgmt_msg_params_init_default(&msg_params, &feature_nego, + sizeof(feature_nego)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_FEATURE_NEGO, &msg_params); + if (err || feature_nego.head.status) { + dev_err(hwdev->dev, "Failed to negotiate feature, err: %d, status: 0x%x\= n", + err, feature_nego.head.status); + return -EINVAL; + } + + if (opcode =3D=3D MGMT_MSG_CMD_OP_GET) + memcpy(s_feature, feature_nego.s_feature, (size * sizeof(u64))); + + return 0; +} + +int hinic3_get_comm_features(struct hinic3_hwdev *hwdev, u64 *s_feature, + u16 size) +{ + return hinic3_comm_features_nego(hwdev, MGMT_MSG_CMD_OP_GET, s_feature, + size); +} + +int hinic3_set_comm_features(struct hinic3_hwdev *hwdev, u64 *s_feature, + u16 size) +{ + return hinic3_comm_features_nego(hwdev, MGMT_MSG_CMD_OP_SET, s_feature, + size); +} + +int hinic3_get_global_attr(struct hinic3_hwdev *hwdev, + struct comm_global_attr *attr) +{ + struct comm_cmd_get_glb_attr get_attr =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + mgmt_msg_params_init_default(&msg_params, &get_attr, sizeof(get_attr)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_GET_GLOBAL_ATTR, &msg_params); + if (err || get_attr.head.status) { + dev_err(hwdev->dev, + "Failed to get global attribute, err: %d, status: 0x%x\n", + err, get_attr.head.status); + return -EIO; + } + + memcpy(attr, &get_attr.attr, sizeof(*attr)); + + return 0; +} + +int hinic3_set_func_svc_used_state(struct hinic3_hwdev *hwdev, u16 svc_typ= e, + u8 state) +{ + struct comm_cmd_set_func_svc_used_state used_state =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + used_state.func_id =3D hinic3_global_func_id(hwdev); + used_state.svc_type =3D svc_type; + used_state.used_state =3D state; + + mgmt_msg_params_init_default(&msg_params, &used_state, + sizeof(used_state)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_SET_FUNC_SVC_USED_STATE, + &msg_params); + if (err || used_state.head.status) { + dev_err(hwdev->dev, + "Failed to set func service used state, err: %d, status: 0x%x\n", + err, used_state.head.status); + return -EIO; + } + + return 0; +} + +int hinic3_set_dma_attr_tbl(struct hinic3_hwdev *hwdev, u8 entry_idx, u8 s= t, + u8 at, u8 ph, u8 no_snooping, u8 tph_en) +{ + struct comm_cmd_set_dma_attr dma_attr =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + dma_attr.func_id =3D hinic3_global_func_id(hwdev); + dma_attr.entry_idx =3D entry_idx; + dma_attr.st =3D st; + dma_attr.at =3D at; + dma_attr.ph =3D ph; + dma_attr.no_snooping =3D no_snooping; + dma_attr.tph_en =3D tph_en; + + mgmt_msg_params_init_default(&msg_params, &dma_attr, sizeof(dma_attr)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_SET_DMA_ATTR, &msg_params); + if (err || dma_attr.head.status) { + dev_err(hwdev->dev, "Failed to set dma attr, err: %d, status: 0x%x\n", + err, dma_attr.head.status); + return -EIO; + } + + return 0; +} + +int hinic3_set_wq_page_size(struct hinic3_hwdev *hwdev, u16 func_idx, + u32 page_size) +{ + struct comm_cmd_cfg_wq_page_size page_size_info =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + page_size_info.func_id =3D func_idx; + page_size_info.page_size =3D ilog2(page_size / HINIC3_MIN_PAGE_SIZE); + page_size_info.opcode =3D MGMT_MSG_CMD_OP_SET; + + mgmt_msg_params_init_default(&msg_params, &page_size_info, + sizeof(page_size_info)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_CFG_PAGESIZE, &msg_params); + if (err || page_size_info.head.status) { + dev_err(hwdev->dev, + "Failed to set wq page size, err: %d, status: 0x%x\n", + err, page_size_info.head.status); + return -EFAULT; + } + + return 0; +} + +int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth) +{ + struct comm_cmd_set_root_ctxt root_ctxt =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + root_ctxt.func_id =3D hinic3_global_func_id(hwdev); + + root_ctxt.set_cmdq_depth =3D 1; + root_ctxt.cmdq_depth =3D ilog2(cmdq_depth); + + mgmt_msg_params_init_default(&msg_params, &root_ctxt, + sizeof(root_ctxt)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_SET_VAT, &msg_params); + if (err || root_ctxt.head.status) { + dev_err(hwdev->dev, + "Failed to set cmdq depth, err: %d, status: 0x%x\n", + err, root_ctxt.head.status); + return -EFAULT; + } + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.h index 2270987b126f..478db3c13281 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h @@ -8,6 +8,8 @@ =20 struct hinic3_hwdev; =20 +#define HINIC3_WQ_PAGE_SIZE_ORDER 8 + struct hinic3_interrupt_info { u32 lli_set; u32 interrupt_coalesc_set; @@ -23,4 +25,19 @@ int hinic3_set_interrupt_cfg_direct(struct hinic3_hwdev = *hwdev, const struct hinic3_interrupt_info *info); int hinic3_func_reset(struct hinic3_hwdev *hwdev, u16 func_id, u64 reset_f= lag); =20 +int hinic3_get_comm_features(struct hinic3_hwdev *hwdev, u64 *s_feature, + u16 size); +int hinic3_set_comm_features(struct hinic3_hwdev *hwdev, u64 *s_feature, + u16 size); +int hinic3_get_global_attr(struct hinic3_hwdev *hwdev, + struct comm_global_attr *attr); +int hinic3_set_func_svc_used_state(struct hinic3_hwdev *hwdev, u16 svc_typ= e, + u8 state); +int hinic3_set_dma_attr_tbl(struct hinic3_hwdev *hwdev, u8 entry_idx, u8 s= t, + u8 at, u8 ph, u8 no_snooping, u8 tph_en); + +int hinic3_set_wq_page_size(struct hinic3_hwdev *hwdev, u16 func_idx, + u32 page_size); +int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth); + #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_intf.h index 379ba4cb042c..b5695dda8fe5 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h @@ -98,6 +98,11 @@ enum comm_func_reset_bits { COMM_FUNC_RESET_BIT_NIC =3D BIT(13), }; =20 +#define COMM_FUNC_RESET_FLAG \ + (COMM_FUNC_RESET_BIT_COMM | COMM_FUNC_RESET_BIT_COMM_CMD_CH | \ + COMM_FUNC_RESET_BIT_FLUSH | COMM_FUNC_RESET_BIT_MQM | \ + COMM_FUNC_RESET_BIT_SMF | COMM_FUNC_RESET_BIT_PF_BW_CFG) + struct comm_cmd_func_reset { struct mgmt_msg_head head; u16 func_id; @@ -114,6 +119,46 @@ struct comm_cmd_feature_nego { u64 s_feature[COMM_MAX_FEATURE_QWORD]; }; =20 +struct comm_global_attr { + u8 max_host_num; + u8 max_pf_num; + u16 vf_id_start; + /* for api cmd to mgmt cpu */ + u8 mgmt_host_node_id; + u8 cmdq_num; + u8 rsvd1[34]; +}; + +struct comm_cmd_get_glb_attr { + struct mgmt_msg_head head; + struct comm_global_attr attr; +}; + +enum comm_func_svc_type { + COMM_FUNC_SVC_T_COMM =3D 0, + COMM_FUNC_SVC_T_NIC =3D 1, +}; + +struct comm_cmd_set_func_svc_used_state { + struct mgmt_msg_head head; + u16 func_id; + u16 svc_type; + u8 used_state; + u8 rsvd[35]; +}; + +struct comm_cmd_set_dma_attr { + struct mgmt_msg_head head; + u16 func_id; + u8 entry_idx; + u8 st; + u8 at; + u8 ph; + u8 no_snooping; + u8 tph_en; + u32 resv1; +}; + struct comm_cmd_set_ceq_ctrl_reg { struct mgmt_msg_head head; u16 func_id; @@ -123,6 +168,28 @@ struct comm_cmd_set_ceq_ctrl_reg { u32 rsvd1; }; =20 +struct comm_cmd_cfg_wq_page_size { + struct mgmt_msg_head head; + u16 func_id; + u8 opcode; + /* real_size=3D4KB*2^page_size, range(0~20) must be checked by driver */ + u8 page_size; + u32 rsvd1; +}; + +struct comm_cmd_set_root_ctxt { + struct mgmt_msg_head head; + u16 func_id; + u8 set_cmdq_depth; + u8 cmdq_depth; + u16 rx_buf_sz; + u8 lro_en; + u8 rsvd1; + u16 sq_depth; + u16 rq_depth; + u64 rsvd2; +}; + struct comm_cmdq_ctxt_info { __le64 curr_wqe_page_pfn; __le64 wq_block_pfn; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.c index d941b365b574..c2327c34a47b 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. =20 +#include "hinic3_cmdq.h" +#include "hinic3_csr.h" #include "hinic3_eqs.h" #include "hinic3_hw_comm.h" #include "hinic3_hwdev.h" @@ -8,6 +10,30 @@ #include "hinic3_mbox.h" #include "hinic3_mgmt.h" =20 +#define HINIC3_PCIE_SNOOP 0 +#define HINIC3_PCIE_TPH_DISABLE 0 + +#define HINIC3_DMA_ATTR_INDIR_IDX_MASK GENMASK(9, 0) +#define HINIC3_DMA_ATTR_INDIR_IDX_SET(val, member) \ + FIELD_PREP(HINIC3_DMA_ATTR_INDIR_##member##_MASK, val) + +#define HINIC3_DMA_ATTR_ENTRY_ST_MASK GENMASK(7, 0) +#define HINIC3_DMA_ATTR_ENTRY_AT_MASK GENMASK(9, 8) +#define HINIC3_DMA_ATTR_ENTRY_PH_MASK GENMASK(11, 10) +#define HINIC3_DMA_ATTR_ENTRY_NO_SNOOPING_MASK BIT(12) +#define HINIC3_DMA_ATTR_ENTRY_TPH_EN_MASK BIT(13) +#define HINIC3_DMA_ATTR_ENTRY_SET(val, member) \ + FIELD_PREP(HINIC3_DMA_ATTR_ENTRY_##member##_MASK, val) + +#define HINIC3_PCIE_ST_DISABLE 0 +#define HINIC3_PCIE_AT_DISABLE 0 +#define HINIC3_PCIE_PH_DISABLE 0 +#define HINIC3_PCIE_MSIX_ATTR_ENTRY 0 + +#define HINIC3_DEFAULT_EQ_MSIX_PENDING_LIMIT 0 +#define HINIC3_DEFAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF +#define HINIC3_DEFAULT_EQ_MSIX_RESEND_TIMER_CFG 7 + #define HINIC3_HWDEV_WQ_NAME "hinic3_hardware" #define HINIC3_WQ_MAX_REQ 10 =20 @@ -16,6 +42,400 @@ enum hinic3_hwdev_init_state { HINIC3_HWDEV_CMDQ_INITED =3D 3, }; =20 +static int hinic3_comm_aeqs_init(struct hinic3_hwdev *hwdev) +{ + struct msix_entry aeq_msix_entries[HINIC3_MAX_AEQS]; + u16 num_aeqs, resp_num_irq, i; + int err; + + num_aeqs =3D hwdev->hwif->attr.num_aeqs; + if (num_aeqs > HINIC3_MAX_AEQS) { + dev_warn(hwdev->dev, "Adjust aeq num to %d\n", + HINIC3_MAX_AEQS); + num_aeqs =3D HINIC3_MAX_AEQS; + } + err =3D hinic3_alloc_irqs(hwdev, num_aeqs, aeq_msix_entries, + &resp_num_irq); + if (err) { + dev_err(hwdev->dev, "Failed to alloc aeq irqs, num_aeqs: %u\n", + num_aeqs); + return err; + } + + if (resp_num_irq < num_aeqs) { + dev_warn(hwdev->dev, "Adjust aeq num to %u\n", + resp_num_irq); + num_aeqs =3D resp_num_irq; + } + + err =3D hinic3_aeqs_init(hwdev, num_aeqs, aeq_msix_entries); + if (err) { + dev_err(hwdev->dev, "Failed to init aeqs\n"); + goto err_free_irqs; + } + + return 0; + +err_free_irqs: + for (i =3D 0; i < num_aeqs; i++) + hinic3_free_irq(hwdev, aeq_msix_entries[i].vector); + + return err; +} + +static int hinic3_comm_ceqs_init(struct hinic3_hwdev *hwdev) +{ + struct msix_entry ceq_msix_entries[HINIC3_MAX_CEQS]; + u16 num_ceqs, resp_num_irq, i; + int err; + + num_ceqs =3D hwdev->hwif->attr.num_ceqs; + if (num_ceqs > HINIC3_MAX_CEQS) { + dev_warn(hwdev->dev, "Adjust ceq num to %d\n", + HINIC3_MAX_CEQS); + num_ceqs =3D HINIC3_MAX_CEQS; + } + + err =3D hinic3_alloc_irqs(hwdev, num_ceqs, ceq_msix_entries, + &resp_num_irq); + if (err) { + dev_err(hwdev->dev, "Failed to alloc ceq irqs, num_ceqs: %u\n", + num_ceqs); + return err; + } + + if (resp_num_irq < num_ceqs) { + dev_warn(hwdev->dev, "Adjust ceq num to %u\n", + resp_num_irq); + num_ceqs =3D resp_num_irq; + } + + err =3D hinic3_ceqs_init(hwdev, num_ceqs, ceq_msix_entries); + if (err) { + dev_err(hwdev->dev, + "Failed to init ceqs, err:%d\n", err); + goto err_free_irqs; + } + + return 0; + +err_free_irqs: + for (i =3D 0; i < num_ceqs; i++) + hinic3_free_irq(hwdev, ceq_msix_entries[i].vector); + + return err; +} + +static int hinic3_comm_mbox_init(struct hinic3_hwdev *hwdev) +{ + int err; + + err =3D hinic3_init_mbox(hwdev); + if (err) + return err; + + hinic3_aeq_register_cb(hwdev, HINIC3_MBX_FROM_FUNC, + hinic3_mbox_func_aeqe_handler); + hinic3_aeq_register_cb(hwdev, HINIC3_MSG_FROM_FW, + hinic3_mgmt_msg_aeqe_handler); + + set_bit(HINIC3_HWDEV_MBOX_INITED, &hwdev->func_state); + + return 0; +} + +static void hinic3_comm_mbox_free(struct hinic3_hwdev *hwdev) +{ + spin_lock_bh(&hwdev->channel_lock); + clear_bit(HINIC3_HWDEV_MBOX_INITED, &hwdev->func_state); + spin_unlock_bh(&hwdev->channel_lock); + hinic3_aeq_unregister_cb(hwdev, HINIC3_MBX_FROM_FUNC); + hinic3_aeq_unregister_cb(hwdev, HINIC3_MSG_FROM_FW); + hinic3_free_mbox(hwdev); +} + +static int init_aeqs_msix_attr(struct hinic3_hwdev *hwdev) +{ + struct hinic3_aeqs *aeqs =3D hwdev->aeqs; + struct hinic3_interrupt_info info =3D {}; + struct hinic3_eq *eq; + u16 q_id; + int err; + + info.interrupt_coalesc_set =3D 1; + info.pending_limit =3D HINIC3_DEFAULT_EQ_MSIX_PENDING_LIMIT; + info.coalesc_timer_cfg =3D HINIC3_DEFAULT_EQ_MSIX_COALESC_TIMER_CFG; + info.resend_timer_cfg =3D HINIC3_DEFAULT_EQ_MSIX_RESEND_TIMER_CFG; + + for (q_id =3D 0; q_id < aeqs->num_aeqs; q_id++) { + eq =3D &aeqs->aeq[q_id]; + info.msix_index =3D eq->msix_entry_idx; + err =3D hinic3_set_interrupt_cfg_direct(hwdev, &info); + if (err) { + dev_err(hwdev->dev, "Set msix attr for aeq %d failed\n", + q_id); + return err; + } + } + + return 0; +} + +static int init_ceqs_msix_attr(struct hinic3_hwdev *hwdev) +{ + struct hinic3_ceqs *ceqs =3D hwdev->ceqs; + struct hinic3_interrupt_info info =3D {}; + struct hinic3_eq *eq; + u16 q_id; + int err; + + info.interrupt_coalesc_set =3D 1; + info.pending_limit =3D HINIC3_DEFAULT_EQ_MSIX_PENDING_LIMIT; + info.coalesc_timer_cfg =3D HINIC3_DEFAULT_EQ_MSIX_COALESC_TIMER_CFG; + info.resend_timer_cfg =3D HINIC3_DEFAULT_EQ_MSIX_RESEND_TIMER_CFG; + + for (q_id =3D 0; q_id < ceqs->num_ceqs; q_id++) { + eq =3D &ceqs->ceq[q_id]; + info.msix_index =3D eq->msix_entry_idx; + err =3D hinic3_set_interrupt_cfg_direct(hwdev, &info); + if (err) { + dev_err(hwdev->dev, "Set msix attr for ceq %u failed\n", + q_id); + return err; + } + } + + return 0; +} + +static int init_basic_mgmt_channel(struct hinic3_hwdev *hwdev) +{ + int err; + + err =3D hinic3_comm_aeqs_init(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init async event queues\n"); + return err; + } + + err =3D hinic3_comm_mbox_init(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init mailbox\n"); + goto err_free_comm_aeqs; + } + + err =3D init_aeqs_msix_attr(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init aeqs msix attr\n"); + goto err_free_comm_mbox; + } + + return 0; + +err_free_comm_mbox: + hinic3_comm_mbox_free(hwdev); +err_free_comm_aeqs: + hinic3_aeqs_free(hwdev); + + return err; +} + +static void free_base_mgmt_channel(struct hinic3_hwdev *hwdev) +{ + hinic3_comm_mbox_free(hwdev); + hinic3_aeqs_free(hwdev); +} + +static int dma_attr_table_init(struct hinic3_hwdev *hwdev) +{ + u32 addr, val, dst_attr; + + /* Indirect access, set entry_idx first */ + addr =3D HINIC3_CSR_DMA_ATTR_INDIR_IDX_ADDR; + val =3D hinic3_hwif_read_reg(hwdev->hwif, addr); + val &=3D ~HINIC3_DMA_ATTR_ENTRY_AT_MASK; + val |=3D HINIC3_DMA_ATTR_INDIR_IDX_SET(HINIC3_PCIE_MSIX_ATTR_ENTRY, IDX); + hinic3_hwif_write_reg(hwdev->hwif, addr, val); + + addr =3D HINIC3_CSR_DMA_ATTR_TBL_ADDR; + val =3D hinic3_hwif_read_reg(hwdev->hwif, addr); + + dst_attr =3D HINIC3_DMA_ATTR_ENTRY_SET(HINIC3_PCIE_ST_DISABLE, ST) | + HINIC3_DMA_ATTR_ENTRY_SET(HINIC3_PCIE_AT_DISABLE, AT) | + HINIC3_DMA_ATTR_ENTRY_SET(HINIC3_PCIE_PH_DISABLE, PH) | + HINIC3_DMA_ATTR_ENTRY_SET(HINIC3_PCIE_SNOOP, NO_SNOOPING) | + HINIC3_DMA_ATTR_ENTRY_SET(HINIC3_PCIE_TPH_DISABLE, TPH_EN); + if (val =3D=3D dst_attr) + return 0; + + return hinic3_set_dma_attr_tbl(hwdev, + HINIC3_PCIE_MSIX_ATTR_ENTRY, + HINIC3_PCIE_ST_DISABLE, + HINIC3_PCIE_AT_DISABLE, + HINIC3_PCIE_PH_DISABLE, + HINIC3_PCIE_SNOOP, + HINIC3_PCIE_TPH_DISABLE); +} + +static int init_basic_attributes(struct hinic3_hwdev *hwdev) +{ + struct comm_global_attr glb_attr; + int err; + + err =3D hinic3_func_reset(hwdev, hinic3_global_func_id(hwdev), + COMM_FUNC_RESET_FLAG); + if (err) + return err; + + err =3D hinic3_get_comm_features(hwdev, hwdev->features, + COMM_MAX_FEATURE_QWORD); + if (err) + return err; + + dev_dbg(hwdev->dev, "Comm hw features: 0x%llx\n", hwdev->features[0]); + + err =3D hinic3_get_global_attr(hwdev, &glb_attr); + if (err) + return err; + + err =3D hinic3_set_func_svc_used_state(hwdev, COMM_FUNC_SVC_T_COMM, 1); + if (err) + return err; + + err =3D dma_attr_table_init(hwdev); + if (err) + return err; + + hwdev->max_cmdq =3D min(glb_attr.cmdq_num, HINIC3_MAX_CMDQ_TYPES); + dev_dbg(hwdev->dev, + "global attribute: max_host: 0x%x, max_pf: 0x%x, vf_id_start: 0x%x, mgmt= node id: 0x%x, cmdq_num: 0x%x\n", + glb_attr.max_host_num, glb_attr.max_pf_num, + glb_attr.vf_id_start, glb_attr.mgmt_host_node_id, + glb_attr.cmdq_num); + + return 0; +} + +static int hinic3_comm_cmdqs_init(struct hinic3_hwdev *hwdev) +{ + int err; + + err =3D hinic3_cmdqs_init(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init cmd queues\n"); + return err; + } + + hinic3_ceq_register_cb(hwdev, HINIC3_CMDQ, hinic3_cmdq_ceq_handler); + + err =3D hinic3_set_cmdq_depth(hwdev, CMDQ_DEPTH); + if (err) { + dev_err(hwdev->dev, "Failed to set cmdq depth\n"); + goto err_free_cmdqs; + } + + set_bit(HINIC3_HWDEV_CMDQ_INITED, &hwdev->func_state); + + return 0; + +err_free_cmdqs: + hinic3_cmdqs_free(hwdev); + + return err; +} + +static void hinic3_comm_cmdqs_free(struct hinic3_hwdev *hwdev) +{ + spin_lock_bh(&hwdev->channel_lock); + clear_bit(HINIC3_HWDEV_CMDQ_INITED, &hwdev->func_state); + spin_unlock_bh(&hwdev->channel_lock); + + hinic3_ceq_unregister_cb(hwdev, HINIC3_CMDQ); + hinic3_cmdqs_free(hwdev); +} + +static int init_cmdqs_channel(struct hinic3_hwdev *hwdev) +{ + int err; + + err =3D hinic3_comm_ceqs_init(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init completion event queues\n"); + return err; + } + + err =3D init_ceqs_msix_attr(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init ceqs msix attr\n"); + goto err_free_ceqs; + } + + hwdev->wq_page_size =3D HINIC3_MIN_PAGE_SIZE << HINIC3_WQ_PAGE_SIZE_ORDER; + err =3D hinic3_set_wq_page_size(hwdev, hinic3_global_func_id(hwdev), + hwdev->wq_page_size); + if (err) { + dev_err(hwdev->dev, "Failed to set wq page size\n"); + goto err_free_ceqs; + } + + err =3D hinic3_comm_cmdqs_init(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init cmd queues\n"); + goto err_reset_wq_page_size; + } + + return 0; + +err_reset_wq_page_size: + hinic3_set_wq_page_size(hwdev, hinic3_global_func_id(hwdev), + HINIC3_MIN_PAGE_SIZE); +err_free_ceqs: + hinic3_ceqs_free(hwdev); + + return err; +} + +static void hinic3_free_cmdqs_channel(struct hinic3_hwdev *hwdev) +{ + hinic3_comm_cmdqs_free(hwdev); + hinic3_ceqs_free(hwdev); +} + +static int hinic3_init_comm_ch(struct hinic3_hwdev *hwdev) +{ + int err; + + err =3D init_basic_mgmt_channel(hwdev); + if (err) + return err; + + err =3D init_basic_attributes(hwdev); + if (err) + goto err_free_basic_mgmt_ch; + + err =3D init_cmdqs_channel(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init cmdq channel\n"); + goto err_clear_func_svc_used_state; + } + + return 0; + +err_clear_func_svc_used_state: + hinic3_set_func_svc_used_state(hwdev, COMM_FUNC_SVC_T_COMM, 0); +err_free_basic_mgmt_ch: + free_base_mgmt_channel(hwdev); + + return err; +} + +static void hinic3_uninit_comm_ch(struct hinic3_hwdev *hwdev) +{ + hinic3_free_cmdqs_channel(hwdev); + hinic3_set_func_svc_used_state(hwdev, COMM_FUNC_SVC_T_COMM, 0); + free_base_mgmt_channel(hwdev); +} + int hinic3_init_hwdev(struct pci_dev *pdev) { struct hinic3_pcidev *pci_adapter =3D pci_get_drvdata(pdev); @@ -53,8 +473,25 @@ int hinic3_init_hwdev(struct pci_dev *pdev) goto err_destroy_workqueue; } =20 + err =3D hinic3_init_comm_ch(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init communication channel\n"); + goto err_free_cfg_mgmt; + } + + err =3D hinic3_set_comm_features(hwdev, hwdev->features, + COMM_MAX_FEATURE_QWORD); + if (err) { + dev_err(hwdev->dev, "Failed to set comm features\n"); + goto err_uninit_comm_ch; + } + return 0; =20 +err_uninit_comm_ch: + hinic3_uninit_comm_ch(hwdev); +err_free_cfg_mgmt: + hinic3_free_cfg_mgmt(hwdev); err_destroy_workqueue: destroy_workqueue(hwdev->workq); err_free_hwif: @@ -68,6 +505,10 @@ int hinic3_init_hwdev(struct pci_dev *pdev) =20 void hinic3_free_hwdev(struct hinic3_hwdev *hwdev) { + u64 drv_features[COMM_MAX_FEATURE_QWORD] =3D {}; + + hinic3_set_comm_features(hwdev, drv_features, COMM_MAX_FEATURE_QWORD); + hinic3_uninit_comm_ch(hwdev); hinic3_free_cfg_mgmt(hwdev); destroy_workqueue(hwdev->workq); hinic3_free_hwif(hwdev); @@ -76,5 +517,19 @@ void hinic3_free_hwdev(struct hinic3_hwdev *hwdev) =20 void hinic3_set_api_stop(struct hinic3_hwdev *hwdev) { - /* Completed by later submission due to LoC limit. */ + struct hinic3_mbox *mbox; + + spin_lock_bh(&hwdev->channel_lock); + if (test_bit(HINIC3_HWDEV_MBOX_INITED, &hwdev->func_state)) { + mbox =3D hwdev->mbox; + spin_lock(&mbox->mbox_lock); + if (mbox->event_flag =3D=3D MBOX_EVENT_START) + mbox->event_flag =3D MBOX_EVENT_TIMEOUT; + spin_unlock(&mbox->mbox_lock); + } + + if (test_bit(HINIC3_HWDEV_CMDQ_INITED, &hwdev->func_state)) + hinic3_cmdq_flush_sync_cmd(hwdev); + + spin_unlock_bh(&hwdev->channel_lock); } --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82FCA3002D1; Fri, 5 Sep 2025 08:29:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060949; cv=none; b=YBHR5XZSCAjzhJ90DE4TdbGcG63j8pTgv20d9g5XdIHHoBsWwCiAid+Fr+Vy//VKCl+Hp+J2hj3BljHdWJ7PbAi1dBYm+tzFz3tDmFPDtQutslRdFXgxcwekGxf0RIfB4mEfDIpobWZ+KhfWx0nRz/xmN5MWJHo0goNXgHpaKl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060949; c=relaxed/simple; bh=Yi/1cpqA8qQen9IzdIh8Dhk8BoklicOLnKI8lRBwco0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pnLRaEnZJUVdX6XiOW1+UlCTaBJzqQ7JrDEV4++6/Y6HbL83Yaj70ew2IJCvSaPZ1bv6NxPFnS/1zvlkbhlJ2allJG0tXcI6ZHLRVvZDpuWWlC+kdzu9OjZGI5sVbq9XR3A0BF6kwLBlMhwrkTTlRggqEBNshDz4WkSk54nWWGk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.105]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4cJ8XD4HJLzQkJs; Fri, 5 Sep 2025 16:24:28 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 48197140147; Fri, 5 Sep 2025 16:29:05 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:03 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 04/14] hinic3: HW capability initialization Date: Fri, 5 Sep 2025 16:28:38 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Use mailbox to get device capability for initializing driver capability. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_hw_cfg.c | 66 +++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_hw_cfg.h | 1 + .../ethernet/huawei/hinic3/hinic3_hw_intf.h | 42 ++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_hwdev.c | 6 ++ 4 files changed, 115 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c b/drivers/n= et/ethernet/huawei/hinic3/hinic3_hw_cfg.c index 8db5e2c9ff10..7827c1f626db 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c @@ -8,6 +8,67 @@ #include "hinic3_hwif.h" #include "hinic3_mbox.h" =20 +#define HINIC3_CFG_MAX_QP 256 + +static void hinic3_parse_pub_res_cap(struct hinic3_hwdev *hwdev, + struct hinic3_dev_cap *cap, + const struct cfg_cmd_dev_cap *dev_cap, + enum hinic3_func_type type) +{ + cap->port_id =3D dev_cap->port_id; + cap->supp_svcs_bitmap =3D dev_cap->svc_cap_en; +} + +static void hinic3_parse_l2nic_res_cap(struct hinic3_hwdev *hwdev, + struct hinic3_dev_cap *cap, + const struct cfg_cmd_dev_cap *dev_cap, + enum hinic3_func_type type) +{ + struct hinic3_nic_service_cap *nic_svc_cap =3D &cap->nic_svc_cap; + + nic_svc_cap->max_sqs =3D min(dev_cap->nic_max_sq_id + 1, + HINIC3_CFG_MAX_QP); +} + +static void hinic3_parse_dev_cap(struct hinic3_hwdev *hwdev, + const struct cfg_cmd_dev_cap *dev_cap, + enum hinic3_func_type type) +{ + struct hinic3_dev_cap *cap =3D &hwdev->cfg_mgmt->cap; + + /* Public resource */ + hinic3_parse_pub_res_cap(hwdev, cap, dev_cap, type); + + /* L2 NIC resource */ + if (hinic3_support_nic(hwdev)) + hinic3_parse_l2nic_res_cap(hwdev, cap, dev_cap, type); +} + +static int get_cap_from_fw(struct hinic3_hwdev *hwdev, + enum hinic3_func_type type) +{ + struct mgmt_msg_params msg_params =3D {}; + struct cfg_cmd_dev_cap dev_cap =3D {}; + int err; + + dev_cap.func_id =3D hinic3_global_func_id(hwdev); + + mgmt_msg_params_init_default(&msg_params, &dev_cap, sizeof(dev_cap)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_CFGM, + CFG_CMD_GET_DEV_CAP, &msg_params); + if (err || dev_cap.head.status) { + dev_err(hwdev->dev, + "Failed to get capability from FW, err: %d, status: 0x%x\n", + err, dev_cap.head.status); + return -EIO; + } + + hinic3_parse_dev_cap(hwdev, &dev_cap, type); + + return 0; +} + static int hinic3_init_irq_info(struct hinic3_hwdev *hwdev) { struct hinic3_cfg_mgmt_info *cfg_mgmt =3D hwdev->cfg_mgmt; @@ -153,6 +214,11 @@ void hinic3_free_irq(struct hinic3_hwdev *hwdev, u32 i= rq_id) mutex_unlock(&irq_info->irq_mutex); } =20 +int hinic3_init_capability(struct hinic3_hwdev *hwdev) +{ + return get_cap_from_fw(hwdev, HINIC3_FUNC_TYPE_VF); +} + bool hinic3_support_nic(struct hinic3_hwdev *hwdev) { return hwdev->cfg_mgmt->cap.supp_svcs_bitmap & diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_hw_cfg.h index 5978cbd56fb2..58806199bf54 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h @@ -49,6 +49,7 @@ int hinic3_alloc_irqs(struct hinic3_hwdev *hwdev, u16 num, struct msix_entry *alloc_arr, u16 *act_num); void hinic3_free_irq(struct hinic3_hwdev *hwdev, u32 irq_id); =20 +int hinic3_init_capability(struct hinic3_hwdev *hwdev); bool hinic3_support_nic(struct hinic3_hwdev *hwdev); u16 hinic3_func_max_qnum(struct hinic3_hwdev *hwdev); u8 hinic3_physical_port_id(struct hinic3_hwdev *hwdev); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_intf.h index b5695dda8fe5..87b43a123edb 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h @@ -51,6 +51,48 @@ static inline void mgmt_msg_params_init_default(struct m= gmt_msg_params *msg_para msg_params->timeout_ms =3D 0; } =20 +enum cfg_cmd { + CFG_CMD_GET_DEV_CAP =3D 0, +}; + +/* Device capabilities, defined by hw */ +struct cfg_cmd_dev_cap { + struct mgmt_msg_head head; + + u16 func_id; + u16 rsvd1; + + /* Public resources */ + u8 host_id; + u8 ep_id; + u8 er_id; + u8 port_id; + + u16 host_total_func; + u8 host_pf_num; + u8 pf_id_start; + u16 host_vf_num; + u16 vf_id_start; + u8 host_oq_id_mask_val; + u8 timer_en; + u8 host_valid_bitmap; + u8 rsvd_host; + + u16 svc_cap_en; + u16 max_vf; + u8 flexq_en; + u8 valid_cos_bitmap; + u8 port_cos_valid_bitmap; + u8 rsvd2[45]; + + /* l2nic */ + u16 nic_max_sq_id; + u16 nic_max_rq_id; + u16 nic_default_num_queues; + + u8 rsvd3[250]; +}; + /* COMM Commands between Driver to fw */ enum comm_cmd { /* Commands for clearing FLR and resources */ diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.c index c2327c34a47b..258e96ac9b76 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -479,6 +479,12 @@ int hinic3_init_hwdev(struct pci_dev *pdev) goto err_free_cfg_mgmt; } =20 + err =3D hinic3_init_capability(hwdev); + if (err) { + dev_err(hwdev->dev, "Failed to init capability\n"); + goto err_uninit_comm_ch; + } + err =3D hinic3_set_comm_features(hwdev, hwdev->features, COMM_MAX_FEATURE_QWORD); if (err) { --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 54CD53043D3; Fri, 5 Sep 2025 08:29:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060954; cv=none; b=KD5H1mDELSQN4d1qJLdz2GTHTJclwNS13fHcykx61a8f9fiC/nZ6L27WDAG82/nXWhRJopihr6hwegZC7EP08TF5d41EmOpLYt27rmBivwafkfCWtNetNVhEwX76IDQ3Z/1lKDmU/7hzyaBxlhmWyumiAEczRXKgn5r4A4XIj4o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060954; c=relaxed/simple; bh=BdLUZ8TXiA8IXqYsfYwdZXA/+837dwMk7kZbQtI7O88=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LOIr3ak2pnWM7XssBTzF8yfYXaiC9dxZclEurw9NSQjuK/y1Hx7PJ/xVBfuLBNiS2+sF4F2VhsUeYx3L6Hu/sRruFY4eaij26Qkm2YRlMgRGNDK0rSK3x4v/EUIQ1Rt/AIKg9hXJZjhIJYF2rBe/y8siMLK+wUsQrePAgQ46aUE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.174]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4cJ8dQ4kxmz14MSH; Fri, 5 Sep 2025 16:28:58 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 9825E1402C8; Fri, 5 Sep 2025 16:29:09 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:05 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 05/14] hinic3: Command Queue flush interfaces Date: Fri, 5 Sep 2025 16:28:39 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Add the data structures and functions for command queue flushing. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_hw_comm.c | 99 +++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_hw_comm.h | 1 + .../ethernet/huawei/hinic3/hinic3_hw_intf.h | 12 +++ .../net/ethernet/huawei/hinic3/hinic3_hwdev.c | 1 + .../net/ethernet/huawei/hinic3/hinic3_hwif.c | 26 +++++ .../net/ethernet/huawei/hinic3/hinic3_hwif.h | 3 + 6 files changed, 142 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.c index b016806c7f67..abb9586e1217 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c @@ -235,3 +235,102 @@ int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev,= u16 cmdq_depth) =20 return 0; } + +#define HINIC3_WAIT_CMDQ_IDLE_TIMEOUT 5000 + +static enum hinic3_wait_return check_cmdq_stop_handler(void *priv_data) +{ + struct hinic3_hwdev *hwdev =3D priv_data; + enum hinic3_cmdq_type cmdq_type; + struct hinic3_cmdqs *cmdqs; + + cmdqs =3D hwdev->cmdqs; + for (cmdq_type =3D 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { + if (!hinic3_cmdq_idle(&cmdqs->cmdq[cmdq_type])) + return HINIC3_WAIT_PROCESS_WAITING; + } + + return HINIC3_WAIT_PROCESS_CPL; +} + +static int wait_cmdq_stop(struct hinic3_hwdev *hwdev) +{ + struct hinic3_cmdqs *cmdqs =3D hwdev->cmdqs; + enum hinic3_cmdq_type cmdq_type; + int err; + + if (!(cmdqs->status & HINIC3_CMDQ_ENABLE)) + return 0; + + cmdqs->status &=3D ~HINIC3_CMDQ_ENABLE; + err =3D hinic3_wait_for_timeout(hwdev, check_cmdq_stop_handler, + HINIC3_WAIT_CMDQ_IDLE_TIMEOUT, + USEC_PER_MSEC); + + if (err) + goto err_reenable_cmdq; + + return 0; + +err_reenable_cmdq: + for (cmdq_type =3D 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { + if (!hinic3_cmdq_idle(&cmdqs->cmdq[cmdq_type])) + dev_err(hwdev->dev, "Cmdq %d is busy\n", cmdq_type); + } + cmdqs->status |=3D HINIC3_CMDQ_ENABLE; + + return err; +} + +int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev) +{ + struct comm_cmd_clear_doorbell clear_db =3D {}; + struct comm_cmd_clear_resource clr_res =3D {}; + struct hinic3_hwif *hwif =3D hwdev->hwif; + struct mgmt_msg_params msg_params =3D {}; + int ret =3D 0; + int err; + + err =3D wait_cmdq_stop(hwdev); + if (err) { + dev_warn(hwdev->dev, "CMDQ is still working, CMDQ timeout value is unrea= sonable\n"); + ret =3D err; + } + + hinic3_disable_doorbell(hwif); + + clear_db.func_id =3D hwif->attr.func_global_idx; + mgmt_msg_params_init_default(&msg_params, &clear_db, sizeof(clear_db)); + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_FLUSH_DOORBELL, &msg_params); + if (err || clear_db.head.status) { + dev_warn(hwdev->dev, "Failed to flush doorbell, err: %d, status: 0x%x\n", + err, clear_db.head.status); + if (err) + ret =3D err; + else + ret =3D -EFAULT; + } + + clr_res.func_id =3D hwif->attr.func_global_idx; + msg_params.buf_in =3D &clr_res; + msg_params.in_size =3D sizeof(clr_res); + err =3D hinic3_send_mbox_to_mgmt_no_ack(hwdev, MGMT_MOD_COMM, + COMM_CMD_START_FLUSH, + &msg_params); + if (err) { + dev_warn(hwdev->dev, "Failed to notice flush message, err: %d\n", + err); + ret =3D err; + } + + hinic3_enable_doorbell(hwif); + + err =3D hinic3_reinit_cmdq_ctxts(hwdev); + if (err) { + dev_warn(hwdev->dev, "Failed to reinit cmdq\n"); + ret =3D err; + } + + return ret; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.h index 478db3c13281..35b93e36e004 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h @@ -39,5 +39,6 @@ int hinic3_set_dma_attr_tbl(struct hinic3_hwdev *hwdev, u= 8 entry_idx, u8 st, int hinic3_set_wq_page_size(struct hinic3_hwdev *hwdev, u16 func_idx, u32 page_size); int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth); +int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_intf.h index 87b43a123edb..f5deddcbc29d 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h @@ -245,6 +245,18 @@ struct comm_cmd_set_cmdq_ctxt { struct comm_cmdq_ctxt_info ctxt; }; =20 +struct comm_cmd_clear_doorbell { + struct mgmt_msg_head head; + u16 func_id; + u16 rsvd1[3]; +}; + +struct comm_cmd_clear_resource { + struct mgmt_msg_head head; + u16 func_id; + u16 rsvd1[3]; +}; + /* Services supported by HW. HW uses these values when delivering events. * HW supports multiple services that are not yet supported by driver * (e.g. RoCE). diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.c index 258e96ac9b76..fa418e4f2654 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -514,6 +514,7 @@ void hinic3_free_hwdev(struct hinic3_hwdev *hwdev) u64 drv_features[COMM_MAX_FEATURE_QWORD] =3D {}; =20 hinic3_set_comm_features(hwdev, drv_features, COMM_MAX_FEATURE_QWORD); + hinic3_func_rx_tx_flush(hwdev); hinic3_uninit_comm_ch(hwdev); hinic3_free_cfg_mgmt(hwdev); destroy_workqueue(hwdev->workq); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_hwif.c index f07bcab51ba5..4c6b5aa0d1df 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c @@ -173,6 +173,32 @@ static enum hinic3_outbound_ctrl hinic3_get_outbound_c= trl_status(struct hinic3_h return HINIC3_AF5_GET(attr5, OUTBOUND_CTRL); } =20 +void hinic3_enable_doorbell(struct hinic3_hwif *hwif) +{ + u32 addr, attr4; + + addr =3D HINIC3_CSR_FUNC_ATTR4_ADDR; + attr4 =3D hinic3_hwif_read_reg(hwif, addr); + + attr4 &=3D ~HINIC3_AF4_DOORBELL_CTRL_MASK; + attr4 |=3D HINIC3_AF4_SET(ENABLE_DOORBELL, DOORBELL_CTRL); + + hinic3_hwif_write_reg(hwif, addr, attr4); +} + +void hinic3_disable_doorbell(struct hinic3_hwif *hwif) +{ + u32 addr, attr4; + + addr =3D HINIC3_CSR_FUNC_ATTR4_ADDR; + attr4 =3D hinic3_hwif_read_reg(hwif, addr); + + attr4 &=3D ~HINIC3_AF4_DOORBELL_CTRL_MASK; + attr4 |=3D HINIC3_AF4_SET(DISABLE_DOORBELL, DOORBELL_CTRL); + + hinic3_hwif_write_reg(hwif, addr, attr4); +} + static int db_area_idx_init(struct hinic3_hwif *hwif, u64 db_base_phy, u8 __iomem *db_base, u64 db_dwqe_len) { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.h b/drivers/net= /ethernet/huawei/hinic3/hinic3_hwif.h index 48e43bfdbfbe..cc93a011c899 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.h @@ -68,6 +68,9 @@ enum hinic3_msix_auto_mask { u32 hinic3_hwif_read_reg(struct hinic3_hwif *hwif, u32 reg); void hinic3_hwif_write_reg(struct hinic3_hwif *hwif, u32 reg, u32 val); =20 +void hinic3_disable_doorbell(struct hinic3_hwif *hwif); +void hinic3_enable_doorbell(struct hinic3_hwif *hwif); + int hinic3_alloc_db_addr(struct hinic3_hwdev *hwdev, void __iomem **db_bas= e, void __iomem **dwqe_base); void hinic3_free_db_addr(struct hinic3_hwdev *hwdev, const u8 __iomem *db_= base); --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B97A30CD93; Fri, 5 Sep 2025 08:29:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060956; cv=none; b=dxBhweP3p95xSIdnqL65BsGbtvY2JIImZ1H1dD27pFEYWup3ZKSN/P7j4eqhTQ4Z8r00rEj1SbkDC0IDLi1siqI09fDinjynShfQ5hBfusIVRMUfpQQOSYpFlIblhAePaGoJlgZjuNeIhThO9mOfcWJvdaejR16DE2xV2WhDp+Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060956; c=relaxed/simple; bh=BlZ5Qyg2AvEvaDO5MPR4REot4z1AfmBDWbmZ5/jyIDI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=RfAcyQYNnIAsHz3TXi1rl4A6yabmKvJIE3X+TsMVYMiKA0LMnk0aHf5+IgttM5u3EC/fjB2xOBzxVeEhxmsYFf+UZjL3xUr29X2rBciJeT7Vsbf7bzrsbK1cSepRT1+DT8dg23LbJAHEiMVafC2+khmg9roy5g93ZFufOVa+pXo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.174]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4cJ8cY4jd2ztTWp; Fri, 5 Sep 2025 16:28:13 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id A87C51402EB; Fri, 5 Sep 2025 16:29:09 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:07 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 06/14] hinic3: Nic_io initialization Date: Fri, 5 Sep 2025 16:28:40 +0800 Message-ID: <0d48674ae76a54bf52dcdba64fb60eb26e7e7e70.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Add nic_io initialization to enable NIC service, initialize function table and negotiate activation of NIC features. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong Reviewed-by: Vadim Fedorenko --- .../net/ethernet/huawei/hinic3/hinic3_hwdev.c | 15 ++++++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 23 +++++++++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 2 + .../ethernet/huawei/hinic3/hinic3_nic_io.c | 51 +++++++++++++++++-- 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.c index fa418e4f2654..95a213133be9 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -436,6 +436,18 @@ static void hinic3_uninit_comm_ch(struct hinic3_hwdev = *hwdev) free_base_mgmt_channel(hwdev); } =20 +static DEFINE_IDA(hinic3_adev_ida); + +static int hinic3_adev_idx_alloc(void) +{ + return ida_alloc(&hinic3_adev_ida, GFP_KERNEL); +} + +static void hinic3_adev_idx_free(int id) +{ + ida_free(&hinic3_adev_ida, id); +} + int hinic3_init_hwdev(struct pci_dev *pdev) { struct hinic3_pcidev *pci_adapter =3D pci_get_drvdata(pdev); @@ -451,6 +463,7 @@ int hinic3_init_hwdev(struct pci_dev *pdev) hwdev->pdev =3D pci_adapter->pdev; hwdev->dev =3D &pci_adapter->pdev->dev; hwdev->func_state =3D 0; + hwdev->dev_id =3D hinic3_adev_idx_alloc(); spin_lock_init(&hwdev->channel_lock); =20 err =3D hinic3_init_hwif(hwdev); @@ -504,6 +517,7 @@ int hinic3_init_hwdev(struct pci_dev *pdev) hinic3_free_hwif(hwdev); err_free_hwdev: pci_adapter->hwdev =3D NULL; + hinic3_adev_idx_free(hwdev->dev_id); kfree(hwdev); =20 return err; @@ -519,6 +533,7 @@ void hinic3_free_hwdev(struct hinic3_hwdev *hwdev) hinic3_free_cfg_mgmt(hwdev); destroy_workqueue(hwdev->workq); hinic3_free_hwif(hwdev); + hinic3_adev_idx_free(hwdev->dev_id); kfree(hwdev); } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index 5b1a91a18c67..049f9536cb86 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -39,6 +39,12 @@ static int hinic3_feature_nego(struct hinic3_hwdev *hwde= v, u8 opcode, return 0; } =20 +int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev) +{ + return hinic3_feature_nego(nic_dev->hwdev, MGMT_MSG_CMD_OP_GET, + &nic_dev->nic_io->feature_cap, 1); +} + int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev) { return hinic3_feature_nego(nic_dev->hwdev, MGMT_MSG_CMD_OP_SET, @@ -82,6 +88,23 @@ static int hinic3_set_function_table(struct hinic3_hwdev= *hwdev, u32 cfg_bitmap, return 0; } =20 +int hinic3_init_function_table(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct l2nic_func_tbl_cfg func_tbl_cfg =3D {}; + u32 cfg_bitmap; + + func_tbl_cfg.mtu =3D 0x3FFF; /* default, max mtu */ + func_tbl_cfg.rx_wqe_buf_size =3D nic_io->rx_buf_len; + + cfg_bitmap =3D BIT(L2NIC_FUNC_TBL_CFG_INIT) | + BIT(L2NIC_FUNC_TBL_CFG_MTU) | + BIT(L2NIC_FUNC_TBL_CFG_RX_BUF_SIZE); + + return hinic3_set_function_table(nic_dev->hwdev, cfg_bitmap, + &func_tbl_cfg); +} + int hinic3_set_port_mtu(struct net_device *netdev, u16 new_mtu) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.h index bf9ce51dc401..6b6851650a37 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h @@ -22,11 +22,13 @@ enum hinic3_nic_event_type { HINIC3_NIC_EVENT_LINK_UP =3D 1, }; =20 +int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev); int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev); bool hinic3_test_support(struct hinic3_nic_dev *nic_dev, enum hinic3_nic_feature_cap feature_bits); void hinic3_update_nic_feature(struct hinic3_nic_dev *nic_dev, u64 feature= _cap); =20 +int hinic3_init_function_table(struct hinic3_nic_dev *nic_dev); int hinic3_set_port_mtu(struct net_device *netdev, u16 new_mtu); =20 int hinic3_set_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vla= n_id, diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.c index 34a1f5bd5ac1..35168f03e0fa 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c @@ -11,11 +11,56 @@ =20 int hinic3_init_nic_io(struct hinic3_nic_dev *nic_dev) { - /* Completed by later submission due to LoC limit. */ - return -EFAULT; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_nic_io *nic_io; + int err; + + nic_io =3D kzalloc(sizeof(*nic_io), GFP_KERNEL); + if (!nic_io) + return -ENOMEM; + + nic_dev->nic_io =3D nic_io; + + err =3D hinic3_set_func_svc_used_state(hwdev, COMM_FUNC_SVC_T_NIC, 1); + if (err) { + dev_err(hwdev->dev, "Failed to set function svc used state\n"); + goto err_free_nicio; + } + + err =3D hinic3_init_function_table(nic_dev); + if (err) { + dev_err(hwdev->dev, "Failed to init function table\n"); + goto err_clear_func_svc_used_state; + } + + nic_io->rx_buf_len =3D nic_dev->rx_buf_len; + + err =3D hinic3_get_nic_feature_from_hw(nic_dev); + if (err) { + dev_err(hwdev->dev, "Failed to get nic features\n"); + goto err_clear_func_svc_used_state; + } + + nic_io->feature_cap &=3D HINIC3_NIC_F_ALL_MASK; + nic_io->feature_cap &=3D HINIC3_NIC_DRV_DEFAULT_FEATURE; + dev_dbg(hwdev->dev, "nic features: 0x%llx\n\n", nic_io->feature_cap); + + return 0; + +err_clear_func_svc_used_state: + hinic3_set_func_svc_used_state(hwdev, COMM_FUNC_SVC_T_NIC, 0); +err_free_nicio: + nic_dev->nic_io =3D NULL; + kfree(nic_io); + + return err; } =20 void hinic3_free_nic_io(struct hinic3_nic_dev *nic_dev) { - /* Completed by later submission due to LoC limit. */ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + + hinic3_set_func_svc_used_state(nic_dev->hwdev, COMM_FUNC_SVC_T_NIC, 0); + nic_dev->nic_io =3D NULL; + kfree(nic_io); } --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5DD43304969; Fri, 5 Sep 2025 08:29:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.190 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060957; cv=none; b=PVZi7o3NPtB85bqGeVjtvzEswsYolrLHJoMD0M9+6+iYpxBiKVmVhAeamq2mdjxNbUwcdQKFstiSpkkOJ/JcppNK1v7l1la2B7FN+ZKqVdjsUuOEoi3HTbLII+2P9G9eyfcwiLYM3f1f9QjR0KNoC5UwKwj4ATrKv8tiuFMKXx0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060957; c=relaxed/simple; bh=5FMNIiSZBBTXpXTec8AIZmd4GbkghmicIv5a7pA8+tk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rEbo3DLX/yUQTW1d2prBtbUQeDFy5/rqUwkA6sgtX7V2s4oXh+A96DGpSHdf/8JDp+XSwBQWfizgG8dNxZGlQVcyt6TOBCCOIyV0msUSMHRJlU09FswrFFqv8qi2F8c7nPbrXjO0HfD4rY0vrohkKxIR3zD7gPCV5OlS9tMmpco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.190 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.17]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4cJ8Z227csz2RW6j; Fri, 5 Sep 2025 16:26:02 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id BA6E21A0188; Fri, 5 Sep 2025 16:29:11 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:10 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 07/14] hinic3: Queue pair endianness improvements Date: Fri, 5 Sep 2025 16:28:41 +0800 Message-ID: <02f2ab84f5e218cd9502794bac7f579d2de27812.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Explicitly use little-endian & big-endian structs to support big endian hosts. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong Reviewed-by: Vadim Fedorenko --- .../ethernet/huawei/hinic3/hinic3_nic_io.h | 15 ++-- .../net/ethernet/huawei/hinic3/hinic3_rx.c | 10 +-- .../net/ethernet/huawei/hinic3/hinic3_rx.h | 24 +++--- .../net/ethernet/huawei/hinic3/hinic3_tx.c | 81 ++++++++++--------- .../net/ethernet/huawei/hinic3/hinic3_tx.h | 18 ++--- 5 files changed, 79 insertions(+), 69 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.h index 865ba6878c48..1808d37e7cf7 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h @@ -75,8 +75,8 @@ static inline u16 hinic3_get_sq_hw_ci(const struct hinic3= _io_queue *sq) #define DB_CFLAG_DP_RQ 1 =20 struct hinic3_nic_db { - u32 db_info; - u32 pi_hi; + __le32 db_info; + __le32 pi_hi; }; =20 static inline void hinic3_write_db(struct hinic3_io_queue *queue, int cos, @@ -84,11 +84,12 @@ static inline void hinic3_write_db(struct hinic3_io_que= ue *queue, int cos, { struct hinic3_nic_db db; =20 - db.db_info =3D DB_INFO_SET(DB_SRC_TYPE, TYPE) | - DB_INFO_SET(cflag, CFLAG) | - DB_INFO_SET(cos, COS) | - DB_INFO_SET(queue->q_id, QID); - db.pi_hi =3D DB_PI_HIGH(pi); + db.db_info =3D + cpu_to_le32(DB_INFO_SET(DB_SRC_TYPE, TYPE) | + DB_INFO_SET(cflag, CFLAG) | + DB_INFO_SET(cos, COS) | + DB_INFO_SET(queue->q_id, QID)); + db.pi_hi =3D cpu_to_le32(DB_PI_HIGH(pi)); =20 writeq(*((u64 *)&db), DB_ADDR(queue, pi)); } diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.c index 860163e9d66c..ac04e3a192ad 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c @@ -66,8 +66,8 @@ static void rq_wqe_buf_set(struct hinic3_io_queue *rq, ui= nt32_t wqe_idx, struct hinic3_rq_wqe *rq_wqe; =20 rq_wqe =3D get_q_element(&rq->wq.qpages, wqe_idx, NULL); - rq_wqe->buf_hi_addr =3D upper_32_bits(dma_addr); - rq_wqe->buf_lo_addr =3D lower_32_bits(dma_addr); + rq_wqe->buf_hi_addr =3D cpu_to_le32(upper_32_bits(dma_addr)); + rq_wqe->buf_lo_addr =3D cpu_to_le32(lower_32_bits(dma_addr)); } =20 static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq) @@ -279,7 +279,7 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct = hinic3_rq_cqe *rx_cqe, if (skb_is_nonlinear(skb)) hinic3_pull_tail(skb); =20 - offload_type =3D rx_cqe->offload_type; + offload_type =3D le32_to_cpu(rx_cqe->offload_type); hinic3_rx_csum(rxq, offload_type, status, skb); =20 num_lro =3D RQ_CQE_STATUS_GET(status, NUM_LRO); @@ -311,14 +311,14 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget) while (likely(nr_pkts < budget)) { sw_ci =3D rxq->cons_idx & rxq->q_mask; rx_cqe =3D rxq->cqe_arr + sw_ci; - status =3D rx_cqe->status; + status =3D le32_to_cpu(rx_cqe->status); if (!RQ_CQE_STATUS_GET(status, RXDONE)) break; =20 /* make sure we read rx_done before packet length */ rmb(); =20 - vlan_len =3D rx_cqe->vlan_len; + vlan_len =3D le32_to_cpu(rx_cqe->vlan_len); pkt_len =3D RQ_CQE_SGE_GET(vlan_len, LEN); if (recv_one_pkt(rxq, rx_cqe, pkt_len, vlan_len, status)) break; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.h index 1cca21858d40..e7b496d13a69 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h @@ -27,21 +27,21 @@ =20 /* RX Completion information that is provided by HW for a specific RX WQE = */ struct hinic3_rq_cqe { - u32 status; - u32 vlan_len; - u32 offload_type; - u32 rsvd3; - u32 rsvd4; - u32 rsvd5; - u32 rsvd6; - u32 pkt_info; + __le32 status; + __le32 vlan_len; + __le32 offload_type; + __le32 rsvd3; + __le32 rsvd4; + __le32 rsvd5; + __le32 rsvd6; + __le32 pkt_info; }; =20 struct hinic3_rq_wqe { - u32 buf_hi_addr; - u32 buf_lo_addr; - u32 cqe_hi_addr; - u32 cqe_lo_addr; + __le32 buf_hi_addr; + __le32 buf_lo_addr; + __le32 cqe_hi_addr; + __le32 cqe_lo_addr; }; =20 struct hinic3_rx_info { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.c index f1c745ee3087..8671bc2e1316 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c @@ -81,10 +81,10 @@ static int hinic3_tx_map_skb(struct net_device *netdev,= struct sk_buff *skb, =20 dma_info[0].len =3D skb_headlen(skb); =20 - wqe_desc->hi_addr =3D upper_32_bits(dma_info[0].dma); - wqe_desc->lo_addr =3D lower_32_bits(dma_info[0].dma); + wqe_desc->hi_addr =3D cpu_to_le32(upper_32_bits(dma_info[0].dma)); + wqe_desc->lo_addr =3D cpu_to_le32(lower_32_bits(dma_info[0].dma)); =20 - wqe_desc->ctrl_len =3D dma_info[0].len; + wqe_desc->ctrl_len =3D cpu_to_le32(dma_info[0].len); =20 for (i =3D 0; i < skb_shinfo(skb)->nr_frags; i++) { frag =3D &(skb_shinfo(skb)->frags[i]); @@ -197,7 +197,8 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struc= t hinic3_sq_task *task, union hinic3_ip ip; u8 l4_proto; =20 - task->pkt_info0 |=3D SQ_TASK_INFO0_SET(1, TUNNEL_FLAG); + task->pkt_info0 |=3D cpu_to_le32(SQ_TASK_INFO0_SET(1, + TUNNEL_FLAG)); =20 ip.hdr =3D skb_network_header(skb); if (ip.v4->version =3D=3D 4) { @@ -226,7 +227,7 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struc= t hinic3_sq_task *task, } } =20 - task->pkt_info0 |=3D SQ_TASK_INFO0_SET(1, INNER_L4_EN); + task->pkt_info0 |=3D cpu_to_le32(SQ_TASK_INFO0_SET(1, INNER_L4_EN)); =20 return 1; } @@ -255,26 +256,28 @@ static void get_inner_l3_l4_type(struct sk_buff *skb,= union hinic3_ip *ip, } } =20 -static void hinic3_set_tso_info(struct hinic3_sq_task *task, u32 *queue_in= fo, +static void hinic3_set_tso_info(struct hinic3_sq_task *task, __le32 *queue= _info, enum hinic3_l4_offload_type l4_offload, u32 offset, u32 mss) { if (l4_offload =3D=3D HINIC3_L4_OFFLOAD_TCP) { - *queue_info |=3D SQ_CTRL_QUEUE_INFO_SET(1, TSO); - task->pkt_info0 |=3D SQ_TASK_INFO0_SET(1, INNER_L4_EN); + *queue_info |=3D cpu_to_le32(SQ_CTRL_QUEUE_INFO_SET(1, TSO)); + task->pkt_info0 |=3D cpu_to_le32(SQ_TASK_INFO0_SET(1, + INNER_L4_EN)); } else if (l4_offload =3D=3D HINIC3_L4_OFFLOAD_UDP) { - *queue_info |=3D SQ_CTRL_QUEUE_INFO_SET(1, UFO); - task->pkt_info0 |=3D SQ_TASK_INFO0_SET(1, INNER_L4_EN); + *queue_info |=3D cpu_to_le32(SQ_CTRL_QUEUE_INFO_SET(1, UFO)); + task->pkt_info0 |=3D cpu_to_le32(SQ_TASK_INFO0_SET(1, + INNER_L4_EN)); } =20 /* enable L3 calculation */ - task->pkt_info0 |=3D SQ_TASK_INFO0_SET(1, INNER_L3_EN); + task->pkt_info0 |=3D cpu_to_le32(SQ_TASK_INFO0_SET(1, INNER_L3_EN)); =20 - *queue_info |=3D SQ_CTRL_QUEUE_INFO_SET(offset >> 1, PLDOFF); + *queue_info |=3D cpu_to_le32(SQ_CTRL_QUEUE_INFO_SET(offset >> 1, PLDOFF)); =20 /* set MSS value */ - *queue_info &=3D ~SQ_CTRL_QUEUE_INFO_MSS_MASK; - *queue_info |=3D SQ_CTRL_QUEUE_INFO_SET(mss, MSS); + *queue_info &=3D cpu_to_le32(~SQ_CTRL_QUEUE_INFO_MSS_MASK); + *queue_info |=3D cpu_to_le32(SQ_CTRL_QUEUE_INFO_SET(mss, MSS)); } =20 static __sum16 csum_magic(union hinic3_ip *ip, unsigned short proto) @@ -284,7 +287,7 @@ static __sum16 csum_magic(union hinic3_ip *ip, unsigned= short proto) csum_ipv6_magic(&ip->v6->saddr, &ip->v6->daddr, 0, proto, 0); } =20 -static int hinic3_tso(struct hinic3_sq_task *task, u32 *queue_info, +static int hinic3_tso(struct hinic3_sq_task *task, __le32 *queue_info, struct sk_buff *skb) { enum hinic3_l4_offload_type l4_offload; @@ -305,15 +308,17 @@ static int hinic3_tso(struct hinic3_sq_task *task, u3= 2 *queue_info, if (skb->encapsulation) { u32 gso_type =3D skb_shinfo(skb)->gso_type; /* L3 checksum is always enabled */ - task->pkt_info0 |=3D SQ_TASK_INFO0_SET(1, OUT_L3_EN); - task->pkt_info0 |=3D SQ_TASK_INFO0_SET(1, TUNNEL_FLAG); + task->pkt_info0 |=3D cpu_to_le32(SQ_TASK_INFO0_SET(1, OUT_L3_EN)); + task->pkt_info0 |=3D cpu_to_le32(SQ_TASK_INFO0_SET(1, + TUNNEL_FLAG)); =20 l4.hdr =3D skb_transport_header(skb); ip.hdr =3D skb_network_header(skb); =20 if (gso_type & SKB_GSO_UDP_TUNNEL_CSUM) { l4.udp->check =3D ~csum_magic(&ip, IPPROTO_UDP); - task->pkt_info0 |=3D SQ_TASK_INFO0_SET(1, OUT_L4_EN); + task->pkt_info0 |=3D + cpu_to_le32(SQ_TASK_INFO0_SET(1, OUT_L4_EN)); } =20 ip.hdr =3D skb_inner_network_header(skb); @@ -343,13 +348,14 @@ static void hinic3_set_vlan_tx_offload(struct hinic3_= sq_task *task, * 2=3Dselect TPID2 in IPSU, 3=3Dselect TPID3 in IPSU, * 4=3Dselect TPID4 in IPSU */ - task->vlan_offload =3D SQ_TASK_INFO3_SET(vlan_tag, VLAN_TAG) | - SQ_TASK_INFO3_SET(vlan_tpid, VLAN_TPID) | - SQ_TASK_INFO3_SET(1, VLAN_TAG_VALID); + task->vlan_offload =3D + cpu_to_le32(SQ_TASK_INFO3_SET(vlan_tag, VLAN_TAG) | + SQ_TASK_INFO3_SET(vlan_tpid, VLAN_TPID) | + SQ_TASK_INFO3_SET(1, VLAN_TAG_VALID)); } =20 static u32 hinic3_tx_offload(struct sk_buff *skb, struct hinic3_sq_task *t= ask, - u32 *queue_info, struct hinic3_txq *txq) + __le32 *queue_info, struct hinic3_txq *txq) { u32 offload =3D 0; int tso_cs_en; @@ -440,39 +446,41 @@ static u16 hinic3_set_wqe_combo(struct hinic3_txq *tx= q, } =20 static void hinic3_prepare_sq_ctrl(struct hinic3_sq_wqe_combo *wqe_combo, - u32 queue_info, int nr_descs, u16 owner) + __le32 queue_info, int nr_descs, u16 owner) { struct hinic3_sq_wqe_desc *wqe_desc =3D wqe_combo->ctrl_bd0; =20 if (wqe_combo->wqe_type =3D=3D SQ_WQE_COMPACT_TYPE) { wqe_desc->ctrl_len |=3D - SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | - SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) | - SQ_CTRL_SET(owner, OWNER); + cpu_to_le32(SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | + SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) | + SQ_CTRL_SET(owner, OWNER)); =20 /* compact wqe queue_info will transfer to chip */ wqe_desc->queue_info =3D 0; return; } =20 - wqe_desc->ctrl_len |=3D SQ_CTRL_SET(nr_descs, BUFDESC_NUM) | - SQ_CTRL_SET(wqe_combo->task_type, TASKSECT_LEN) | - SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | - SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) | - SQ_CTRL_SET(owner, OWNER); + wqe_desc->ctrl_len |=3D + cpu_to_le32(SQ_CTRL_SET(nr_descs, BUFDESC_NUM) | + SQ_CTRL_SET(wqe_combo->task_type, TASKSECT_LEN) | + SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | + SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) | + SQ_CTRL_SET(owner, OWNER)); =20 wqe_desc->queue_info =3D queue_info; - wqe_desc->queue_info |=3D SQ_CTRL_QUEUE_INFO_SET(1, UC); + wqe_desc->queue_info |=3D cpu_to_le32(SQ_CTRL_QUEUE_INFO_SET(1, UC)); =20 if (!SQ_CTRL_QUEUE_INFO_GET(wqe_desc->queue_info, MSS)) { wqe_desc->queue_info |=3D - SQ_CTRL_QUEUE_INFO_SET(HINIC3_TX_MSS_DEFAULT, MSS); + cpu_to_le32(SQ_CTRL_QUEUE_INFO_SET(HINIC3_TX_MSS_DEFAULT, MSS)); } else if (SQ_CTRL_QUEUE_INFO_GET(wqe_desc->queue_info, MSS) < HINIC3_TX_MSS_MIN) { /* mss should not be less than 80 */ - wqe_desc->queue_info &=3D ~SQ_CTRL_QUEUE_INFO_MSS_MASK; + wqe_desc->queue_info &=3D + cpu_to_le32(~SQ_CTRL_QUEUE_INFO_MSS_MASK); wqe_desc->queue_info |=3D - SQ_CTRL_QUEUE_INFO_SET(HINIC3_TX_MSS_MIN, MSS); + cpu_to_le32(SQ_CTRL_QUEUE_INFO_SET(HINIC3_TX_MSS_MIN, MSS)); } } =20 @@ -482,12 +490,13 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff= *skb, { struct hinic3_sq_wqe_combo wqe_combo =3D {}; struct hinic3_tx_info *tx_info; - u32 offload, queue_info =3D 0; struct hinic3_sq_task task; u16 wqebb_cnt, num_sge; + __le32 queue_info =3D 0; u16 saved_wq_prod_idx; u16 owner, pi =3D 0; u8 saved_sq_owner; + u32 offload; int err; =20 if (unlikely(skb->len < MIN_SKB_LEN)) { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.h index 9e505cc19dd5..21dfe879a29a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h @@ -58,7 +58,7 @@ enum hinic3_tx_offload_type { #define SQ_CTRL_QUEUE_INFO_SET(val, member) \ FIELD_PREP(SQ_CTRL_QUEUE_INFO_##member##_MASK, val) #define SQ_CTRL_QUEUE_INFO_GET(val, member) \ - FIELD_GET(SQ_CTRL_QUEUE_INFO_##member##_MASK, val) + FIELD_GET(SQ_CTRL_QUEUE_INFO_##member##_MASK, le32_to_cpu(val)) =20 #define SQ_CTRL_MAX_PLDOFF 221 =20 @@ -77,17 +77,17 @@ enum hinic3_tx_offload_type { FIELD_PREP(SQ_TASK_INFO3_##member##_MASK, val) =20 struct hinic3_sq_wqe_desc { - u32 ctrl_len; - u32 queue_info; - u32 hi_addr; - u32 lo_addr; + __le32 ctrl_len; + __le32 queue_info; + __le32 hi_addr; + __le32 lo_addr; }; =20 struct hinic3_sq_task { - u32 pkt_info0; - u32 ip_identify; - u32 rsvd; - u32 vlan_offload; + __le32 pkt_info0; + __le32 ip_identify; + __le32 rsvd; + __le32 vlan_offload; }; =20 struct hinic3_sq_wqe_combo { --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga06-in.huawei.com (szxga06-in.huawei.com [45.249.212.32]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 45DCB30EF75; Fri, 5 Sep 2025 08:29:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.32 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060959; cv=none; b=oEYEoYyu1MlsiZoDzeheNOBk6tnG6aVmW8IEVbGSdOmjSdSSZv9PNBjTNLKZONoz1xux6tm22tvoljRInLKYwndFN4sHuNGhOL7JmCWRFuD1A7nIGWiCRJKVYmIjN6EAaoKdgRsiy9N8sUEcrbvyJNNS3vaUXJZHM5xqkH6v4cw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060959; c=relaxed/simple; bh=kfNBZjk9bkaDNYATZx1dzDRum/q3M4nWR6Qlxr0hkuI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sSWIU0+/sAt0KwVX4glNPYeC7dpK3pEVcyfPlrhS9VR4bwTNjY3idbV5wNjICHGF0xqNKF0uvOMIIPxmfiQP3t52tOnXfbdhq6aZTtAzaq0X+PC3ViICdLSHK1FIB+u63kvWw2mahLXXNSUpea89q905tDOVlS54Wv9go7IG+mQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.32 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.44]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4cJ8g20m9Yz3tZV9; Fri, 5 Sep 2025 16:30:22 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id CF8CB140279; Fri, 5 Sep 2025 16:29:13 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:12 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 08/14] hinic3: Queue pair resource initialization Date: Fri, 5 Sep 2025 16:28:42 +0800 Message-ID: <9edfab97e33bb1c608eb441f2959f84a592116b1.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Add Tx & Rx queue resources and functions for packet transmission and reception. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../huawei/hinic3/hinic3_netdev_ops.c | 251 +++++++++++++++++- .../ethernet/huawei/hinic3/hinic3_nic_io.c | 240 +++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_nic_io.h | 21 ++ .../net/ethernet/huawei/hinic3/hinic3_rx.c | 152 ++++++++++- .../net/ethernet/huawei/hinic3/hinic3_rx.h | 12 + .../net/ethernet/huawei/hinic3/hinic3_tx.c | 69 +++++ .../net/ethernet/huawei/hinic3/hinic3_tx.h | 10 + 7 files changed, 748 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index 71104a6b8bef..c0010308f7d6 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -11,16 +11,259 @@ #include "hinic3_rx.h" #include "hinic3_tx.h" =20 +/* try to modify the number of irq to the target number, + * and return the actual number of irq. + */ +static u16 hinic3_qp_irq_change(struct net_device *netdev, + u16 dst_num_qp_irq) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct msix_entry *qps_msix_entries; + u16 resp_irq_num, irq_num_gap, i; + u16 idx; + int err; + + qps_msix_entries =3D nic_dev->qps_msix_entries; + if (dst_num_qp_irq > nic_dev->num_qp_irq) { + irq_num_gap =3D dst_num_qp_irq - nic_dev->num_qp_irq; + err =3D hinic3_alloc_irqs(nic_dev->hwdev, irq_num_gap, + &qps_msix_entries[nic_dev->num_qp_irq], + &resp_irq_num); + if (err) { + netdev_err(netdev, "Failed to alloc irqs\n"); + return nic_dev->num_qp_irq; + } + + nic_dev->num_qp_irq +=3D resp_irq_num; + } else if (dst_num_qp_irq < nic_dev->num_qp_irq) { + irq_num_gap =3D nic_dev->num_qp_irq - dst_num_qp_irq; + for (i =3D 0; i < irq_num_gap; i++) { + idx =3D (nic_dev->num_qp_irq - i) - 1; + hinic3_free_irq(nic_dev->hwdev, + qps_msix_entries[idx].vector); + qps_msix_entries[idx].vector =3D 0; + qps_msix_entries[idx].entry =3D 0; + } + nic_dev->num_qp_irq =3D dst_num_qp_irq; + } + + return nic_dev->num_qp_irq; +} + +static void hinic3_config_num_qps(struct net_device *netdev, + struct hinic3_dyna_txrxq_params *q_params) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u16 alloc_num_irq, cur_num_irq; + u16 dst_num_irq; + + if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) + q_params->num_qps =3D 1; + + if (nic_dev->num_qp_irq >=3D q_params->num_qps) + goto out; + + cur_num_irq =3D nic_dev->num_qp_irq; + + alloc_num_irq =3D hinic3_qp_irq_change(netdev, q_params->num_qps); + if (alloc_num_irq < q_params->num_qps) { + q_params->num_qps =3D alloc_num_irq; + netdev_warn(netdev, "Can not get enough irqs, adjust num_qps to %u\n", + q_params->num_qps); + + /* The current irq may be in use, we must keep it */ + dst_num_irq =3D max_t(u16, cur_num_irq, q_params->num_qps); + hinic3_qp_irq_change(netdev, dst_num_irq); + } + +out: + netdev_dbg(netdev, "Finally num_qps: %u\n", q_params->num_qps); +} + +static int hinic3_setup_num_qps(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + nic_dev->num_qp_irq =3D 0; + + nic_dev->qps_msix_entries =3D kcalloc(nic_dev->max_qps, + sizeof(struct msix_entry), + GFP_KERNEL); + if (!nic_dev->qps_msix_entries) + return -ENOMEM; + + hinic3_config_num_qps(netdev, &nic_dev->q_params); + + return 0; +} + +static void hinic3_destroy_num_qps(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u16 i; + + for (i =3D 0; i < nic_dev->num_qp_irq; i++) + hinic3_free_irq(nic_dev->hwdev, + nic_dev->qps_msix_entries[i].vector); + + kfree(nic_dev->qps_msix_entries); +} + +static int hinic3_alloc_txrxq_resources(struct net_device *netdev, + struct hinic3_dyna_txrxq_params *q_params) +{ + int err; + + q_params->txqs_res =3D kcalloc(q_params->num_qps, + sizeof(*q_params->txqs_res), GFP_KERNEL); + if (!q_params->txqs_res) + return -ENOMEM; + + q_params->rxqs_res =3D kcalloc(q_params->num_qps, + sizeof(*q_params->rxqs_res), GFP_KERNEL); + if (!q_params->rxqs_res) { + err =3D -ENOMEM; + goto err_free_txqs_res_arr; + } + + q_params->irq_cfg =3D kcalloc(q_params->num_qps, + sizeof(*q_params->irq_cfg), GFP_KERNEL); + if (!q_params->irq_cfg) { + err =3D -ENOMEM; + goto err_free_rxqs_res_arr; + } + + err =3D hinic3_alloc_txqs_res(netdev, q_params->num_qps, + q_params->sq_depth, q_params->txqs_res); + if (err) { + netdev_err(netdev, "Failed to alloc txqs resource\n"); + goto err_free_irq_cfg; + } + + err =3D hinic3_alloc_rxqs_res(netdev, q_params->num_qps, + q_params->rq_depth, q_params->rxqs_res); + if (err) { + netdev_err(netdev, "Failed to alloc rxqs resource\n"); + goto err_free_txqs_res; + } + + return 0; + +err_free_txqs_res: + hinic3_free_txqs_res(netdev, q_params->num_qps, q_params->sq_depth, + q_params->txqs_res); +err_free_irq_cfg: + kfree(q_params->irq_cfg); + q_params->irq_cfg =3D NULL; +err_free_rxqs_res_arr: + kfree(q_params->rxqs_res); + q_params->rxqs_res =3D NULL; +err_free_txqs_res_arr: + kfree(q_params->txqs_res); + q_params->txqs_res =3D NULL; + + return err; +} + +static void hinic3_free_txrxq_resources(struct net_device *netdev, + struct hinic3_dyna_txrxq_params *q_params) +{ + hinic3_free_rxqs_res(netdev, q_params->num_qps, q_params->rq_depth, + q_params->rxqs_res); + hinic3_free_txqs_res(netdev, q_params->num_qps, q_params->sq_depth, + q_params->txqs_res); + + kfree(q_params->irq_cfg); + q_params->irq_cfg =3D NULL; + + kfree(q_params->rxqs_res); + q_params->rxqs_res =3D NULL; + + kfree(q_params->txqs_res); + q_params->txqs_res =3D NULL; +} + +static int hinic3_alloc_channel_resources(struct net_device *netdev, + struct hinic3_dyna_qp_params *qp_params, + struct hinic3_dyna_txrxq_params *trxq_params) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err; + + qp_params->num_qps =3D trxq_params->num_qps; + qp_params->sq_depth =3D trxq_params->sq_depth; + qp_params->rq_depth =3D trxq_params->rq_depth; + + err =3D hinic3_alloc_qps(nic_dev, qp_params); + if (err) { + netdev_err(netdev, "Failed to alloc qps\n"); + return err; + } + + err =3D hinic3_alloc_txrxq_resources(netdev, trxq_params); + if (err) { + netdev_err(netdev, "Failed to alloc txrxq resources\n"); + hinic3_free_qps(nic_dev, qp_params); + return err; + } + + return 0; +} + +static void hinic3_free_channel_resources(struct net_device *netdev, + struct hinic3_dyna_qp_params *qp_params, + struct hinic3_dyna_txrxq_params *trxq_params) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + hinic3_free_txrxq_resources(netdev, trxq_params); + hinic3_free_qps(nic_dev, qp_params); +} + static int hinic3_open(struct net_device *netdev) { - /* Completed by later submission due to LoC limit. */ - return -EFAULT; + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_dyna_qp_params qp_params; + int err; + + err =3D hinic3_init_nicio_res(nic_dev); + if (err) { + netdev_err(netdev, "Failed to init nicio resources\n"); + return err; + } + + err =3D hinic3_setup_num_qps(netdev); + if (err) { + netdev_err(netdev, "Failed to setup num_qps\n"); + goto err_free_nicio_res; + } + + err =3D hinic3_alloc_channel_resources(netdev, &qp_params, + &nic_dev->q_params); + if (err) + goto err_destroy_num_qps; + + hinic3_init_qps(nic_dev, &qp_params); + + return 0; + +err_destroy_num_qps: + hinic3_destroy_num_qps(netdev); +err_free_nicio_res: + hinic3_free_nicio_res(nic_dev); + + return err; } =20 static int hinic3_close(struct net_device *netdev) { - /* Completed by later submission due to LoC limit. */ - return -EFAULT; + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_dyna_qp_params qp_params; + + hinic3_uninit_qps(nic_dev, &qp_params); + hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); + + return 0; } =20 static int hinic3_change_mtu(struct net_device *netdev, int new_mtu) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.c index 35168f03e0fa..8f06ff5c377d 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c @@ -9,6 +9,14 @@ #include "hinic3_nic_dev.h" #include "hinic3_nic_io.h" =20 +#define HINIC3_CI_Q_ADDR_SIZE (64) + +#define HINIC3_CI_TABLE_SIZE(num_qps) \ + (ALIGN((num_qps) * HINIC3_CI_Q_ADDR_SIZE, HINIC3_MIN_PAGE_SIZE)) + +#define HINIC3_CI_VADDR(base_addr, q_id) \ + ((u8 *)(base_addr) + (q_id) * HINIC3_CI_Q_ADDR_SIZE) + int hinic3_init_nic_io(struct hinic3_nic_dev *nic_dev) { struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; @@ -64,3 +72,235 @@ void hinic3_free_nic_io(struct hinic3_nic_dev *nic_dev) nic_dev->nic_io =3D NULL; kfree(nic_io); } + +int hinic3_init_nicio_res(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + void __iomem *db_base; + int err; + + nic_io->max_qps =3D hinic3_func_max_qnum(hwdev); + + err =3D hinic3_alloc_db_addr(hwdev, &db_base, NULL); + if (err) { + dev_err(hwdev->dev, "Failed to allocate doorbell for sqs\n"); + return err; + } + nic_io->sqs_db_addr =3D db_base; + + err =3D hinic3_alloc_db_addr(hwdev, &db_base, NULL); + if (err) { + hinic3_free_db_addr(hwdev, nic_io->sqs_db_addr); + dev_err(hwdev->dev, "Failed to allocate doorbell for rqs\n"); + return err; + } + nic_io->rqs_db_addr =3D db_base; + + nic_io->ci_vaddr_base =3D + dma_alloc_coherent(hwdev->dev, + HINIC3_CI_TABLE_SIZE(nic_io->max_qps), + &nic_io->ci_dma_base, + GFP_KERNEL); + if (!nic_io->ci_vaddr_base) { + hinic3_free_db_addr(hwdev, nic_io->sqs_db_addr); + hinic3_free_db_addr(hwdev, nic_io->rqs_db_addr); + return -ENOMEM; + } + + return 0; +} + +void hinic3_free_nicio_res(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + + dma_free_coherent(hwdev->dev, + HINIC3_CI_TABLE_SIZE(nic_io->max_qps), + nic_io->ci_vaddr_base, nic_io->ci_dma_base); + + hinic3_free_db_addr(hwdev, nic_io->sqs_db_addr); + hinic3_free_db_addr(hwdev, nic_io->rqs_db_addr); +} + +static int hinic3_create_sq(struct hinic3_hwdev *hwdev, + struct hinic3_io_queue *sq, + u16 q_id, u32 sq_depth, u16 sq_msix_idx) +{ + int err; + + /* sq used & hardware request init 1 */ + sq->owner =3D 1; + + sq->q_id =3D q_id; + sq->msix_entry_idx =3D sq_msix_idx; + + err =3D hinic3_wq_create(hwdev, &sq->wq, sq_depth, + BIT(HINIC3_SQ_WQEBB_SHIFT)); + if (err) { + dev_err(hwdev->dev, "Failed to create tx queue %u wq\n", + q_id); + return err; + } + + return 0; +} + +static int hinic3_create_rq(struct hinic3_hwdev *hwdev, + struct hinic3_io_queue *rq, + u16 q_id, u32 rq_depth, u16 rq_msix_idx) +{ + int err; + + rq->q_id =3D q_id; + rq->msix_entry_idx =3D rq_msix_idx; + + err =3D hinic3_wq_create(hwdev, &rq->wq, rq_depth, + BIT(HINIC3_RQ_WQEBB_SHIFT + + HINIC3_NORMAL_RQ_WQE)); + if (err) { + dev_err(hwdev->dev, "Failed to create rx queue %u wq\n", + q_id); + return err; + } + + return 0; +} + +static int hinic3_create_qp(struct hinic3_hwdev *hwdev, + struct hinic3_io_queue *sq, + struct hinic3_io_queue *rq, u16 q_id, u32 sq_depth, + u32 rq_depth, u16 qp_msix_idx) +{ + int err; + + err =3D hinic3_create_sq(hwdev, sq, q_id, sq_depth, qp_msix_idx); + if (err) { + dev_err(hwdev->dev, "Failed to create sq, qid: %u\n", + q_id); + return err; + } + + err =3D hinic3_create_rq(hwdev, rq, q_id, rq_depth, qp_msix_idx); + if (err) { + dev_err(hwdev->dev, "Failed to create rq, qid: %u\n", + q_id); + goto err_destroy_sq_wq; + } + + return 0; + +err_destroy_sq_wq: + hinic3_wq_destroy(hwdev, &sq->wq); + + return err; +} + +static void hinic3_destroy_qp(struct hinic3_hwdev *hwdev, + struct hinic3_io_queue *sq, + struct hinic3_io_queue *rq) +{ + hinic3_wq_destroy(hwdev, &sq->wq); + hinic3_wq_destroy(hwdev, &rq->wq); +} + +int hinic3_alloc_qps(struct hinic3_nic_dev *nic_dev, + struct hinic3_dyna_qp_params *qp_params) +{ + struct msix_entry *qps_msix_entries =3D nic_dev->qps_msix_entries; + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_io_queue *sqs; + struct hinic3_io_queue *rqs; + u16 q_id; + int err; + + if (qp_params->num_qps > nic_io->max_qps || !qp_params->num_qps) + return -EINVAL; + + sqs =3D kcalloc(qp_params->num_qps, sizeof(*sqs), GFP_KERNEL); + if (!sqs) { + err =3D -ENOMEM; + goto err_out; + } + + rqs =3D kcalloc(qp_params->num_qps, sizeof(*rqs), GFP_KERNEL); + if (!rqs) { + err =3D -ENOMEM; + goto err_free_sqs; + } + + for (q_id =3D 0; q_id < qp_params->num_qps; q_id++) { + err =3D hinic3_create_qp(hwdev, &sqs[q_id], &rqs[q_id], q_id, + qp_params->sq_depth, qp_params->rq_depth, + qps_msix_entries[q_id].entry); + if (err) { + dev_err(hwdev->dev, "Failed to allocate qp %u, err: %d\n", + q_id, err); + goto err_destroy_qp; + } + } + + qp_params->sqs =3D sqs; + qp_params->rqs =3D rqs; + + return 0; + +err_destroy_qp: + while (q_id > 0) { + q_id--; + hinic3_destroy_qp(hwdev, &sqs[q_id], &rqs[q_id]); + } + kfree(rqs); +err_free_sqs: + kfree(sqs); +err_out: + return err; +} + +void hinic3_free_qps(struct hinic3_nic_dev *nic_dev, + struct hinic3_dyna_qp_params *qp_params) +{ + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + u16 q_id; + + for (q_id =3D 0; q_id < qp_params->num_qps; q_id++) + hinic3_destroy_qp(hwdev, &qp_params->sqs[q_id], + &qp_params->rqs[q_id]); + + kfree(qp_params->sqs); + kfree(qp_params->rqs); +} + +void hinic3_init_qps(struct hinic3_nic_dev *nic_dev, + struct hinic3_dyna_qp_params *qp_params) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_io_queue *sqs =3D qp_params->sqs; + struct hinic3_io_queue *rqs =3D qp_params->rqs; + u16 q_id; + + nic_io->num_qps =3D qp_params->num_qps; + nic_io->sq =3D qp_params->sqs; + nic_io->rq =3D qp_params->rqs; + for (q_id =3D 0; q_id < nic_io->num_qps; q_id++) { + sqs[q_id].cons_idx_addr =3D + (u16 *)HINIC3_CI_VADDR(nic_io->ci_vaddr_base, q_id); + /* clear ci value */ + WRITE_ONCE(*sqs[q_id].cons_idx_addr, 0); + + sqs[q_id].db_addr =3D nic_io->sqs_db_addr; + rqs[q_id].db_addr =3D nic_io->rqs_db_addr; + } +} + +void hinic3_uninit_qps(struct hinic3_nic_dev *nic_dev, + struct hinic3_dyna_qp_params *qp_params) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + + qp_params->sqs =3D nic_io->sq; + qp_params->rqs =3D nic_io->rq; + qp_params->num_qps =3D nic_io->num_qps; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.h index 1808d37e7cf7..c103095c37ef 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h @@ -94,6 +94,15 @@ static inline void hinic3_write_db(struct hinic3_io_queu= e *queue, int cos, writeq(*((u64 *)&db), DB_ADDR(queue, pi)); } =20 +struct hinic3_dyna_qp_params { + u16 num_qps; + u32 sq_depth; + u32 rq_depth; + + struct hinic3_io_queue *sqs; + struct hinic3_io_queue *rqs; +}; + struct hinic3_nic_io { struct hinic3_io_queue *sq; struct hinic3_io_queue *rq; @@ -118,4 +127,16 @@ struct hinic3_nic_io { int hinic3_init_nic_io(struct hinic3_nic_dev *nic_dev); void hinic3_free_nic_io(struct hinic3_nic_dev *nic_dev); =20 +int hinic3_init_nicio_res(struct hinic3_nic_dev *nic_dev); +void hinic3_free_nicio_res(struct hinic3_nic_dev *nic_dev); + +int hinic3_alloc_qps(struct hinic3_nic_dev *nic_dev, + struct hinic3_dyna_qp_params *qp_params); +void hinic3_free_qps(struct hinic3_nic_dev *nic_dev, + struct hinic3_dyna_qp_params *qp_params); +void hinic3_init_qps(struct hinic3_nic_dev *nic_dev, + struct hinic3_dyna_qp_params *qp_params); +void hinic3_uninit_qps(struct hinic3_nic_dev *nic_dev, + struct hinic3_dyna_qp_params *qp_params); + #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.c index ac04e3a192ad..e81f7c19bf63 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c @@ -35,13 +35,35 @@ =20 int hinic3_alloc_rxqs(struct net_device *netdev) { - /* Completed by later submission due to LoC limit. */ - return -EFAULT; + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct pci_dev *pdev =3D nic_dev->pdev; + u16 num_rxqs =3D nic_dev->max_qps; + struct hinic3_rxq *rxq; + u16 q_id; + + nic_dev->rxqs =3D kcalloc(num_rxqs, sizeof(*nic_dev->rxqs), GFP_KERNEL); + if (!nic_dev->rxqs) + return -ENOMEM; + + for (q_id =3D 0; q_id < num_rxqs; q_id++) { + rxq =3D &nic_dev->rxqs[q_id]; + rxq->netdev =3D netdev; + rxq->dev =3D &pdev->dev; + rxq->q_id =3D q_id; + rxq->buf_len =3D nic_dev->rx_buf_len; + rxq->buf_len_shift =3D ilog2(nic_dev->rx_buf_len); + rxq->q_depth =3D nic_dev->q_params.rq_depth; + rxq->q_mask =3D nic_dev->q_params.rq_depth - 1; + } + + return 0; } =20 void hinic3_free_rxqs(struct net_device *netdev) { - /* Completed by later submission due to LoC limit. */ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + kfree(nic_dev->rxqs); } =20 static int rx_alloc_mapped_page(struct page_pool *page_pool, @@ -50,6 +72,9 @@ static int rx_alloc_mapped_page(struct page_pool *page_po= ol, struct page *page; u32 page_offset; =20 + if (likely(rx_info->page)) + return 0; + page =3D page_pool_dev_alloc_frag(page_pool, &page_offset, buf_len); if (unlikely(!page)) return -ENOMEM; @@ -102,6 +127,41 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *r= xq) return i; } =20 +static u32 hinic3_alloc_rx_buffers(struct hinic3_dyna_rxq_res *rqres, + u32 rq_depth, u16 buf_len) +{ + u32 free_wqebbs =3D rq_depth - 1; + u32 idx; + int err; + + for (idx =3D 0; idx < free_wqebbs; idx++) { + err =3D rx_alloc_mapped_page(rqres->page_pool, + &rqres->rx_info[idx], buf_len); + if (err) + break; + } + + return idx; +} + +static void hinic3_free_rx_buffers(struct hinic3_dyna_rxq_res *rqres, + u32 q_depth) +{ + struct hinic3_rx_info *rx_info; + u32 i; + + /* Free all the Rx ring sk_buffs */ + for (i =3D 0; i < q_depth; i++) { + rx_info =3D &rqres->rx_info[i]; + + if (rx_info->page) { + page_pool_put_full_page(rqres->page_pool, + rx_info->page, false); + rx_info->page =3D NULL; + } + } +} + static void hinic3_add_rx_frag(struct hinic3_rxq *rxq, struct hinic3_rx_info *rx_info, struct sk_buff *skb, u32 size) @@ -299,6 +359,92 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct= hinic3_rq_cqe *rx_cqe, return 0; } =20 +int hinic3_alloc_rxqs_res(struct net_device *netdev, u16 num_rq, + u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res) +{ + u64 cqe_mem_size =3D sizeof(struct hinic3_rq_cqe) * rq_depth; + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct page_pool_params pp_params =3D {}; + struct hinic3_dyna_rxq_res *rqres; + u32 pkt_idx; + int idx; + + for (idx =3D 0; idx < num_rq; idx++) { + rqres =3D &rxqs_res[idx]; + rqres->rx_info =3D kcalloc(rq_depth, sizeof(*rqres->rx_info), + GFP_KERNEL); + if (!rqres->rx_info) + goto err_free_rqres; + + rqres->cqe_start_vaddr =3D + dma_alloc_coherent(&nic_dev->pdev->dev, cqe_mem_size, + &rqres->cqe_start_paddr, GFP_KERNEL); + if (!rqres->cqe_start_vaddr) { + netdev_err(netdev, "Failed to alloc rxq%d rx cqe\n", + idx); + goto err_free_rx_info; + } + + pp_params.flags =3D PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; + pp_params.pool_size =3D rq_depth * nic_dev->rx_buf_len / + PAGE_SIZE; + pp_params.nid =3D dev_to_node(&nic_dev->pdev->dev); + pp_params.dev =3D &nic_dev->pdev->dev; + pp_params.dma_dir =3D DMA_FROM_DEVICE; + pp_params.max_len =3D PAGE_SIZE; + rqres->page_pool =3D page_pool_create(&pp_params); + if (!rqres->page_pool) { + netdev_err(netdev, "Failed to create rxq%d page pool\n", + idx); + goto err_free_cqe; + } + + pkt_idx =3D hinic3_alloc_rx_buffers(rqres, rq_depth, + nic_dev->rx_buf_len); + if (!pkt_idx) { + netdev_err(netdev, "Failed to alloc rxq%d rx buffers\n", + idx); + goto err_destroy_page_pool; + } + rqres->next_to_alloc =3D pkt_idx; + } + + return 0; + +err_destroy_page_pool: + page_pool_destroy(rqres->page_pool); +err_free_cqe: + dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size, + rqres->cqe_start_vaddr, + rqres->cqe_start_paddr); +err_free_rx_info: + kfree(rqres->rx_info); +err_free_rqres: + hinic3_free_rxqs_res(netdev, idx, rq_depth, rxqs_res); + + return -ENOMEM; +} + +void hinic3_free_rxqs_res(struct net_device *netdev, u16 num_rq, + u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res) +{ + u64 cqe_mem_size =3D sizeof(struct hinic3_rq_cqe) * rq_depth; + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_dyna_rxq_res *rqres; + int idx; + + for (idx =3D 0; idx < num_rq; idx++) { + rqres =3D &rxqs_res[idx]; + + hinic3_free_rx_buffers(rqres, rq_depth); + page_pool_destroy(rqres->page_pool); + dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size, + rqres->cqe_start_vaddr, + rqres->cqe_start_paddr); + kfree(rqres->rx_info); + } +} + int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(rxq->netdev); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.h index e7b496d13a69..ec3f45c3688a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h @@ -82,9 +82,21 @@ struct hinic3_rxq { dma_addr_t cqe_start_paddr; } ____cacheline_aligned; =20 +struct hinic3_dyna_rxq_res { + u16 next_to_alloc; + struct hinic3_rx_info *rx_info; + dma_addr_t cqe_start_paddr; + void *cqe_start_vaddr; + struct page_pool *page_pool; +}; + int hinic3_alloc_rxqs(struct net_device *netdev); void hinic3_free_rxqs(struct net_device *netdev); =20 +int hinic3_alloc_rxqs_res(struct net_device *netdev, u16 num_rq, + u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res); +void hinic3_free_rxqs_res(struct net_device *netdev, u16 num_rq, + u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res); int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.c index 8671bc2e1316..3c63fe071999 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c @@ -138,6 +138,23 @@ static void hinic3_tx_unmap_skb(struct net_device *net= dev, dma_info[0].len, DMA_TO_DEVICE); } =20 +static void free_all_tx_skbs(struct net_device *netdev, u32 sq_depth, + struct hinic3_tx_info *tx_info_arr) +{ + struct hinic3_tx_info *tx_info; + u32 idx; + + for (idx =3D 0; idx < sq_depth; idx++) { + tx_info =3D &tx_info_arr[idx]; + if (tx_info->skb) { + hinic3_tx_unmap_skb(netdev, tx_info->skb, + tx_info->dma_info); + dev_kfree_skb_any(tx_info->skb); + tx_info->skb =3D NULL; + } + } +} + union hinic3_ip { struct iphdr *v4; struct ipv6hdr *v6; @@ -633,6 +650,58 @@ void hinic3_flush_txqs(struct net_device *netdev) #define HINIC3_BDS_PER_SQ_WQEBB \ (HINIC3_SQ_WQEBB_SIZE / sizeof(struct hinic3_sq_bufdesc)) =20 +int hinic3_alloc_txqs_res(struct net_device *netdev, u16 num_sq, + u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res) +{ + struct hinic3_dyna_txq_res *tqres; + int idx; + + for (idx =3D 0; idx < num_sq; idx++) { + tqres =3D &txqs_res[idx]; + + tqres->tx_info =3D kcalloc(sq_depth, sizeof(*tqres->tx_info), + GFP_KERNEL); + if (!tqres->tx_info) + goto err_free_tqres; + + tqres->bds =3D kcalloc(sq_depth * HINIC3_BDS_PER_SQ_WQEBB + + HINIC3_MAX_SQ_SGE, sizeof(*tqres->bds), + GFP_KERNEL); + if (!tqres->bds) { + kfree(tqres->tx_info); + goto err_free_tqres; + } + } + + return 0; + +err_free_tqres: + while (idx > 0) { + idx--; + tqres =3D &txqs_res[idx]; + + kfree(tqres->bds); + kfree(tqres->tx_info); + } + + return -ENOMEM; +} + +void hinic3_free_txqs_res(struct net_device *netdev, u16 num_sq, + u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res) +{ + struct hinic3_dyna_txq_res *tqres; + int idx; + + for (idx =3D 0; idx < num_sq; idx++) { + tqres =3D &txqs_res[idx]; + + free_all_tx_skbs(netdev, sq_depth, tqres->tx_info); + kfree(tqres->bds); + kfree(tqres->tx_info); + } +} + bool hinic3_tx_poll(struct hinic3_txq *txq, int budget) { struct net_device *netdev =3D txq->netdev; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.h index 21dfe879a29a..9ec6968b6688 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h @@ -125,9 +125,19 @@ struct hinic3_txq { struct hinic3_io_queue *sq; } ____cacheline_aligned; =20 +struct hinic3_dyna_txq_res { + struct hinic3_tx_info *tx_info; + struct hinic3_dma_info *bds; +}; + int hinic3_alloc_txqs(struct net_device *netdev); void hinic3_free_txqs(struct net_device *netdev); =20 +int hinic3_alloc_txqs_res(struct net_device *netdev, u16 num_sq, + u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res); +void hinic3_free_txqs_res(struct net_device *netdev, u16 num_sq, + u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res); + netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, struct net_device *netd= ev); bool hinic3_tx_poll(struct hinic3_txq *txq, int budget); void hinic3_flush_txqs(struct net_device *netdev); --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga06-in.huawei.com (szxga06-in.huawei.com [45.249.212.32]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8732A3043D3; Fri, 5 Sep 2025 08:29:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.32 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060961; cv=none; b=QtFYYI9fVPDx0xpCLuhU27lhhsrJWVbgePS6nG6K8mTRCiB8btfjG8P0PNjTsc+E/Ns7Hc2Sx5U9kySOh0soSOOYs9TGdAa+6rHdW3kOYUbaOq26FJqBRNzwAUO99ZNmeiARG8tA4hv/lXi/sz1Aw6wliCKR5/+mBOrt4+0zOuY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060961; c=relaxed/simple; bh=h39V4Kv+31ge7m/bwlTgwf2BOR+K1W4AYk6OoRGiU88=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=R4PKXo5m+gpRbJTVNUkLA94fbN/LGPJ4zEEG4hpA4u44SLgB9aX/dlF/hcFoNp96cqTMNih7oVkquoNrTfkXl7SFYp00l72cr3kDauR6ZJ8UBFUtSFssO/EicSDIi7JKDtdlfoZjEUq5RjXeS/zd6DZf5i/aXkO3zIPoTzkZLLE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.32 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.163]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4cJ8g41NXrz3tZW3; Fri, 5 Sep 2025 16:30:24 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id E79AA180042; Fri, 5 Sep 2025 16:29:15 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:14 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 09/14] hinic3: Queue pair context initialization Date: Fri, 5 Sep 2025 16:28:43 +0800 Message-ID: <157c8ec4da66697b72593453fbf35055c04324cd.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Initialize queue pair context of hardware interaction. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_hw_comm.c | 88 +++ .../ethernet/huawei/hinic3/hinic3_hw_comm.h | 3 + .../huawei/hinic3/hinic3_mgmt_interface.h | 20 + .../huawei/hinic3/hinic3_netdev_ops.c | 42 ++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 35 ++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 12 + .../ethernet/huawei/hinic3/hinic3_nic_io.c | 579 ++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_nic_io.h | 3 + 8 files changed, 782 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.c index abb9586e1217..b314ff13a99d 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c @@ -334,3 +334,91 @@ int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev) =20 return ret; } + +static int get_hw_rx_buf_size_idx(int rx_buf_sz, u16 *buf_sz_idx) +{ + /* Supported RX buffer sizes in bytes. Configured by array index. */ + static const int supported_sizes[16] =3D { + [0] =3D 32, [1] =3D 64, [2] =3D 96, [3] =3D 128, + [4] =3D 192, [5] =3D 256, [6] =3D 384, [7] =3D 512, + [8] =3D 768, [9] =3D 1024, [10] =3D 1536, [11] =3D 2048, + [12] =3D 3072, [13] =3D 4096, [14] =3D 8192, [15] =3D 16384, + }; + u16 idx; + + /* Scan from biggest to smallest. Choose supported size that is equal or + * smaller. For smaller value HW will under-utilize posted buffers. For + * bigger value HW may overrun posted buffers. + */ + idx =3D ARRAY_SIZE(supported_sizes); + while (idx > 0) { + idx--; + if (supported_sizes[idx] <=3D rx_buf_sz) { + *buf_sz_idx =3D idx; + return 0; + } + } + + return -EINVAL; +} + +int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_= depth, + int rx_buf_sz) +{ + struct comm_cmd_set_root_ctxt root_ctxt =3D {}; + struct mgmt_msg_params msg_params =3D {}; + u16 buf_sz_idx; + int err; + + err =3D get_hw_rx_buf_size_idx(rx_buf_sz, &buf_sz_idx); + if (err) + return err; + + root_ctxt.func_id =3D hinic3_global_func_id(hwdev); + + root_ctxt.set_cmdq_depth =3D 0; + root_ctxt.cmdq_depth =3D 0; + + root_ctxt.lro_en =3D 1; + + root_ctxt.rq_depth =3D ilog2(rq_depth); + root_ctxt.rx_buf_sz =3D buf_sz_idx; + root_ctxt.sq_depth =3D ilog2(sq_depth); + + mgmt_msg_params_init_default(&msg_params, &root_ctxt, + sizeof(root_ctxt)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_SET_VAT, &msg_params); + if (err || root_ctxt.head.status) { + dev_err(hwdev->dev, + "Failed to set root context, err: %d, status: 0x%x\n", + err, root_ctxt.head.status); + return -EFAULT; + } + + return 0; +} + +int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev) +{ + struct comm_cmd_set_root_ctxt root_ctxt =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + root_ctxt.func_id =3D hinic3_global_func_id(hwdev); + + mgmt_msg_params_init_default(&msg_params, &root_ctxt, + sizeof(root_ctxt)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_SET_VAT, &msg_params); + if (err || root_ctxt.head.status) { + dev_err(hwdev->dev, + "Failed to set root context, err: %d, status: 0x%x\n", + err, root_ctxt.head.status); + return -EFAULT; + } + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.h index 35b93e36e004..304f5691f0c2 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h @@ -40,5 +40,8 @@ int hinic3_set_wq_page_size(struct hinic3_hwdev *hwdev, u= 16 func_idx, u32 page_size); int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth); int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev); +int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_= depth, + int rx_buf_sz); +int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/d= rivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index c4434efdc7f7..b891290a3d6e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -56,6 +56,19 @@ struct l2nic_cmd_update_mac { u8 new_mac[ETH_ALEN]; }; =20 +struct l2nic_cmd_set_ci_attr { + struct mgmt_msg_head msg_head; + u16 func_idx; + u8 dma_attr_off; + u8 pending_limit; + u8 coalescing_time; + u8 intr_en; + u16 intr_idx; + u32 l2nic_sqn; + u32 rsvd; + u64 ci_addr; +}; + struct l2nic_cmd_force_pkt_drop { struct mgmt_msg_head msg_head; u8 port; @@ -82,6 +95,13 @@ enum l2nic_cmd { L2NIC_CMD_MAX =3D 256, }; =20 +/* NIC CMDQ MODE */ +enum l2nic_ucode_cmd { + L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX =3D 0, + L2NIC_UCODE_CMD_CLEAN_QUEUE_CTX =3D 1, + L2NIC_UCODE_CMD_SET_RSS_INDIR_TBL =3D 4, +}; + enum hinic3_nic_feature_cap { HINIC3_NIC_F_CSUM =3D BIT(0), HINIC3_NIC_F_SCTP_CRC =3D BIT(1), diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index c0010308f7d6..2c5c7051e72e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -220,6 +220,39 @@ static void hinic3_free_channel_resources(struct net_d= evice *netdev, hinic3_free_qps(nic_dev, qp_params); } =20 +static int hinic3_open_channel(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err; + + err =3D hinic3_init_qp_ctxts(nic_dev); + if (err) { + netdev_err(netdev, "Failed to init qps\n"); + return err; + } + + err =3D hinic3_qps_irq_init(netdev); + if (err) { + netdev_err(netdev, "Failed to init txrxq irq\n"); + goto err_free_qp_ctxts; + } + + return 0; + +err_free_qp_ctxts: + hinic3_free_qp_ctxts(nic_dev); + + return err; +} + +static void hinic3_close_channel(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + hinic3_qps_irq_uninit(netdev); + hinic3_free_qp_ctxts(nic_dev); +} + static int hinic3_open(struct net_device *netdev) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); @@ -245,8 +278,16 @@ static int hinic3_open(struct net_device *netdev) =20 hinic3_init_qps(nic_dev, &qp_params); =20 + err =3D hinic3_open_channel(netdev); + if (err) + goto err_uninit_qps; + return 0; =20 +err_uninit_qps: + hinic3_uninit_qps(nic_dev, &qp_params); + hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); + err_destroy_num_qps: hinic3_destroy_num_qps(netdev); err_free_nicio_res: @@ -260,6 +301,7 @@ static int hinic3_close(struct net_device *netdev) struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); struct hinic3_dyna_qp_params qp_params; =20 + hinic3_close_channel(netdev); hinic3_uninit_qps(nic_dev, &qp_params); hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index 049f9536cb86..5b18764781d4 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -229,6 +229,41 @@ int hinic3_update_mac(struct hinic3_hwdev *hwdev, cons= t u8 *old_mac, err, mac_info.msg_head.status); return -EIO; } + + return 0; +} + +int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, struct hinic3_sq_attr = *attr) +{ + struct l2nic_cmd_set_ci_attr cons_idx_attr =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + cons_idx_attr.func_idx =3D hinic3_global_func_id(hwdev); + cons_idx_attr.dma_attr_off =3D attr->dma_attr_off; + cons_idx_attr.pending_limit =3D attr->pending_limit; + cons_idx_attr.coalescing_time =3D attr->coalescing_time; + + if (attr->intr_en) { + cons_idx_attr.intr_en =3D attr->intr_en; + cons_idx_attr.intr_idx =3D attr->intr_idx; + } + + cons_idx_attr.l2nic_sqn =3D attr->l2nic_sqn; + cons_idx_attr.ci_addr =3D attr->ci_dma_base; + + mgmt_msg_params_init_default(&msg_params, &cons_idx_attr, + sizeof(cons_idx_attr)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_SET_SQ_CI_ATTR, &msg_params); + if (err || cons_idx_attr.msg_head.status) { + dev_err(hwdev->dev, + "Failed to set ci attribute table, err: %d, status: 0x%x\n", + err, cons_idx_attr.msg_head.status); + return -EFAULT; + } + return 0; } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.h index 6b6851650a37..dd1615745f02 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h @@ -22,6 +22,16 @@ enum hinic3_nic_event_type { HINIC3_NIC_EVENT_LINK_UP =3D 1, }; =20 +struct hinic3_sq_attr { + u8 dma_attr_off; + u8 pending_limit; + u8 coalescing_time; + u8 intr_en; + u16 intr_idx; + u32 l2nic_sqn; + u64 ci_dma_base; +}; + int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev); int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev); bool hinic3_test_support(struct hinic3_nic_dev *nic_dev, @@ -38,6 +48,8 @@ int hinic3_del_mac(struct hinic3_hwdev *hwdev, const u8 *= mac_addr, u16 vlan_id, int hinic3_update_mac(struct hinic3_hwdev *hwdev, const u8 *old_mac, u8 *new_mac, u16 vlan_id, u16 func_id); =20 +int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, + struct hinic3_sq_attr *attr); int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.c index 8f06ff5c377d..65881f6bf2af 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. =20 +#include "hinic3_cmdq.h" #include "hinic3_hw_comm.h" #include "hinic3_hw_intf.h" #include "hinic3_hwdev.h" @@ -9,6 +10,11 @@ #include "hinic3_nic_dev.h" #include "hinic3_nic_io.h" =20 +#define HINIC3_DEFAULT_TX_CI_PENDING_LIMIT 1 +#define HINIC3_DEFAULT_TX_CI_COALESCING_TIME 1 +#define HINIC3_DEFAULT_DROP_THD_ON (0xFFFF) +#define HINIC3_DEFAULT_DROP_THD_OFF 0 + #define HINIC3_CI_Q_ADDR_SIZE (64) =20 #define HINIC3_CI_TABLE_SIZE(num_qps) \ @@ -17,6 +23,186 @@ #define HINIC3_CI_VADDR(base_addr, q_id) \ ((u8 *)(base_addr) + (q_id) * HINIC3_CI_Q_ADDR_SIZE) =20 +#define HINIC3_CI_PADDR(base_paddr, q_id) \ + ((base_paddr) + (q_id) * HINIC3_CI_Q_ADDR_SIZE) + +#define SQ_WQ_PREFETCH_MAX 1 +#define SQ_WQ_PREFETCH_MIN 1 +#define SQ_WQ_PREFETCH_THRESHOLD 16 + +#define RQ_WQ_PREFETCH_MAX 4 +#define RQ_WQ_PREFETCH_MIN 1 +#define RQ_WQ_PREFETCH_THRESHOLD 256 + +/* (2048 - 8) / 64 */ +#define HINIC3_Q_CTXT_MAX 31 + +enum hinic3_qp_ctxt_type { + HINIC3_QP_CTXT_TYPE_SQ =3D 0, + HINIC3_QP_CTXT_TYPE_RQ =3D 1, +}; + +struct hinic3_qp_ctxt_hdr { + __le16 num_queues; + __le16 queue_type; + __le16 start_qid; + __le16 rsvd; +}; + +struct hinic3_sq_ctxt { + __le32 ci_pi; + __le32 drop_mode_sp; + __le32 wq_pfn_hi_owner; + __le32 wq_pfn_lo; + + __le32 rsvd0; + __le32 pkt_drop_thd; + __le32 global_sq_id; + __le32 vlan_ceq_attr; + + __le32 pref_cache; + __le32 pref_ci_owner; + __le32 pref_wq_pfn_hi_ci; + __le32 pref_wq_pfn_lo; + + __le32 rsvd8; + __le32 rsvd9; + __le32 wq_block_pfn_hi; + __le32 wq_block_pfn_lo; +}; + +struct hinic3_rq_ctxt { + __le32 ci_pi; + __le32 ceq_attr; + __le32 wq_pfn_hi_type_owner; + __le32 wq_pfn_lo; + + __le32 rsvd[3]; + __le32 cqe_sge_len; + + __le32 pref_cache; + __le32 pref_ci_owner; + __le32 pref_wq_pfn_hi_ci; + __le32 pref_wq_pfn_lo; + + __le32 pi_paddr_hi; + __le32 pi_paddr_lo; + __le32 wq_block_pfn_hi; + __le32 wq_block_pfn_lo; +}; + +struct hinic3_sq_ctxt_block { + struct hinic3_qp_ctxt_hdr cmdq_hdr; + struct hinic3_sq_ctxt sq_ctxt[HINIC3_Q_CTXT_MAX]; +}; + +struct hinic3_rq_ctxt_block { + struct hinic3_qp_ctxt_hdr cmdq_hdr; + struct hinic3_rq_ctxt rq_ctxt[HINIC3_Q_CTXT_MAX]; +}; + +struct hinic3_clean_queue_ctxt { + struct hinic3_qp_ctxt_hdr cmdq_hdr; + __le32 rsvd; +}; + +#define SQ_CTXT_SIZE(num_sqs) \ + (sizeof(struct hinic3_qp_ctxt_hdr) + \ + (num_sqs) * sizeof(struct hinic3_sq_ctxt)) + +#define RQ_CTXT_SIZE(num_rqs) \ + (sizeof(struct hinic3_qp_ctxt_hdr) + \ + (num_rqs) * sizeof(struct hinic3_rq_ctxt)) + +#define SQ_CTXT_PREF_CI_HI_SHIFT 12 +#define SQ_CTXT_PREF_CI_HI(val) ((val) >> SQ_CTXT_PREF_CI_HI_SH= IFT) + +#define SQ_CTXT_PI_IDX_MASK GENMASK(15, 0) +#define SQ_CTXT_CI_IDX_MASK GENMASK(31, 16) +#define SQ_CTXT_CI_PI_SET(val, member) \ + FIELD_PREP(SQ_CTXT_##member##_MASK, val) + +#define SQ_CTXT_MODE_SP_FLAG_MASK BIT(0) +#define SQ_CTXT_MODE_PKT_DROP_MASK BIT(1) +#define SQ_CTXT_MODE_SET(val, member) \ + FIELD_PREP(SQ_CTXT_MODE_##member##_MASK, val) + +#define SQ_CTXT_WQ_PAGE_HI_PFN_MASK GENMASK(19, 0) +#define SQ_CTXT_WQ_PAGE_OWNER_MASK BIT(23) +#define SQ_CTXT_WQ_PAGE_SET(val, member) \ + FIELD_PREP(SQ_CTXT_WQ_PAGE_##member##_MASK, val) + +#define SQ_CTXT_PKT_DROP_THD_ON_MASK GENMASK(15, 0) +#define SQ_CTXT_PKT_DROP_THD_OFF_MASK GENMASK(31, 16) +#define SQ_CTXT_PKT_DROP_THD_SET(val, member) \ + FIELD_PREP(SQ_CTXT_PKT_DROP_##member##_MASK, val) + +#define SQ_CTXT_GLOBAL_SQ_ID_MASK GENMASK(12, 0) +#define SQ_CTXT_GLOBAL_QUEUE_ID_SET(val, member) \ + FIELD_PREP(SQ_CTXT_##member##_MASK, val) + +#define SQ_CTXT_VLAN_INSERT_MODE_MASK GENMASK(20, 19) +#define SQ_CTXT_VLAN_CEQ_EN_MASK BIT(23) +#define SQ_CTXT_VLAN_CEQ_SET(val, member) \ + FIELD_PREP(SQ_CTXT_VLAN_##member##_MASK, val) + +#define SQ_CTXT_PREF_CACHE_THRESHOLD_MASK GENMASK(13, 0) +#define SQ_CTXT_PREF_CACHE_MAX_MASK GENMASK(24, 14) +#define SQ_CTXT_PREF_CACHE_MIN_MASK GENMASK(31, 25) + +#define SQ_CTXT_PREF_CI_HI_MASK GENMASK(3, 0) +#define SQ_CTXT_PREF_OWNER_MASK BIT(4) + +#define SQ_CTXT_PREF_WQ_PFN_HI_MASK GENMASK(19, 0) +#define SQ_CTXT_PREF_CI_LOW_MASK GENMASK(31, 20) +#define SQ_CTXT_PREF_SET(val, member) \ + FIELD_PREP(SQ_CTXT_PREF_##member##_MASK, val) + +#define SQ_CTXT_WQ_BLOCK_PFN_HI_MASK GENMASK(22, 0) +#define SQ_CTXT_WQ_BLOCK_SET(val, member) \ + FIELD_PREP(SQ_CTXT_WQ_BLOCK_##member##_MASK, val) + +#define RQ_CTXT_PI_IDX_MASK GENMASK(15, 0) +#define RQ_CTXT_CI_IDX_MASK GENMASK(31, 16) +#define RQ_CTXT_CI_PI_SET(val, member) \ + FIELD_PREP(RQ_CTXT_##member##_MASK, val) + +#define RQ_CTXT_CEQ_ATTR_INTR_MASK GENMASK(30, 21) +#define RQ_CTXT_CEQ_ATTR_EN_MASK BIT(31) +#define RQ_CTXT_CEQ_ATTR_SET(val, member) \ + FIELD_PREP(RQ_CTXT_CEQ_ATTR_##member##_MASK, val) + +#define RQ_CTXT_WQ_PAGE_HI_PFN_MASK GENMASK(19, 0) +#define RQ_CTXT_WQ_PAGE_WQE_TYPE_MASK GENMASK(29, 28) +#define RQ_CTXT_WQ_PAGE_OWNER_MASK BIT(31) +#define RQ_CTXT_WQ_PAGE_SET(val, member) \ + FIELD_PREP(RQ_CTXT_WQ_PAGE_##member##_MASK, val) + +#define RQ_CTXT_CQE_LEN_MASK GENMASK(29, 28) +#define RQ_CTXT_CQE_LEN_SET(val, member) \ + FIELD_PREP(RQ_CTXT_##member##_MASK, val) + +#define RQ_CTXT_PREF_CACHE_THRESHOLD_MASK GENMASK(13, 0) +#define RQ_CTXT_PREF_CACHE_MAX_MASK GENMASK(24, 14) +#define RQ_CTXT_PREF_CACHE_MIN_MASK GENMASK(31, 25) + +#define RQ_CTXT_PREF_CI_HI_MASK GENMASK(3, 0) +#define RQ_CTXT_PREF_OWNER_MASK BIT(4) + +#define RQ_CTXT_PREF_WQ_PFN_HI_MASK GENMASK(19, 0) +#define RQ_CTXT_PREF_CI_LOW_MASK GENMASK(31, 20) +#define RQ_CTXT_PREF_SET(val, member) \ + FIELD_PREP(RQ_CTXT_PREF_##member##_MASK, val) + +#define RQ_CTXT_WQ_BLOCK_PFN_HI_MASK GENMASK(22, 0) +#define RQ_CTXT_WQ_BLOCK_SET(val, member) \ + FIELD_PREP(RQ_CTXT_WQ_BLOCK_##member##_MASK, val) + +#define WQ_PAGE_PFN_SHIFT 12 +#define WQ_BLOCK_PFN_SHIFT 9 +#define WQ_PAGE_PFN(page_addr) ((page_addr) >> WQ_PAGE_PFN_SHIFT) +#define WQ_BLOCK_PFN(page_addr) ((page_addr) >> WQ_BLOCK_PFN_SHIFT) + int hinic3_init_nic_io(struct hinic3_nic_dev *nic_dev) { struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; @@ -304,3 +490,396 @@ void hinic3_uninit_qps(struct hinic3_nic_dev *nic_dev, qp_params->rqs =3D nic_io->rq; qp_params->num_qps =3D nic_io->num_qps; } + +static void hinic3_qp_prepare_cmdq_header(struct hinic3_qp_ctxt_hdr *qp_ct= xt_hdr, + enum hinic3_qp_ctxt_type ctxt_type, + u16 num_queues, u16 q_id) +{ + qp_ctxt_hdr->queue_type =3D cpu_to_le16(ctxt_type); + qp_ctxt_hdr->num_queues =3D cpu_to_le16(num_queues); + qp_ctxt_hdr->start_qid =3D cpu_to_le16(q_id); + qp_ctxt_hdr->rsvd =3D 0; +} + +static void hinic3_sq_prepare_ctxt(struct hinic3_io_queue *sq, u16 sq_id, + struct hinic3_sq_ctxt *sq_ctxt) +{ + u64 wq_page_addr, wq_page_pfn, wq_block_pfn; + u32 wq_block_pfn_hi, wq_block_pfn_lo; + u32 wq_page_pfn_hi, wq_page_pfn_lo; + u16 pi_start, ci_start; + + ci_start =3D hinic3_get_sq_local_ci(sq); + pi_start =3D hinic3_get_sq_local_pi(sq); + + wq_page_addr =3D hinic3_wq_get_first_wqe_page_addr(&sq->wq); + + wq_page_pfn =3D WQ_PAGE_PFN(wq_page_addr); + wq_page_pfn_hi =3D upper_32_bits(wq_page_pfn); + wq_page_pfn_lo =3D lower_32_bits(wq_page_pfn); + + wq_block_pfn =3D WQ_BLOCK_PFN(sq->wq.wq_block_paddr); + wq_block_pfn_hi =3D upper_32_bits(wq_block_pfn); + wq_block_pfn_lo =3D lower_32_bits(wq_block_pfn); + + sq_ctxt->ci_pi =3D + cpu_to_le32(SQ_CTXT_CI_PI_SET(ci_start, CI_IDX) | + SQ_CTXT_CI_PI_SET(pi_start, PI_IDX)); + + sq_ctxt->drop_mode_sp =3D + cpu_to_le32(SQ_CTXT_MODE_SET(0, SP_FLAG) | + SQ_CTXT_MODE_SET(0, PKT_DROP)); + + sq_ctxt->wq_pfn_hi_owner =3D + cpu_to_le32(SQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) | + SQ_CTXT_WQ_PAGE_SET(1, OWNER)); + + sq_ctxt->wq_pfn_lo =3D cpu_to_le32(wq_page_pfn_lo); + + sq_ctxt->pkt_drop_thd =3D + cpu_to_le32(SQ_CTXT_PKT_DROP_THD_SET(HINIC3_DEFAULT_DROP_THD_ON, THD_ON)= | + SQ_CTXT_PKT_DROP_THD_SET(HINIC3_DEFAULT_DROP_THD_OFF, THD_OFF)); + + sq_ctxt->global_sq_id =3D + cpu_to_le32(SQ_CTXT_GLOBAL_QUEUE_ID_SET((u32)sq_id, + GLOBAL_SQ_ID)); + + /* enable insert c-vlan by default */ + sq_ctxt->vlan_ceq_attr =3D + cpu_to_le32(SQ_CTXT_VLAN_CEQ_SET(0, CEQ_EN) | + SQ_CTXT_VLAN_CEQ_SET(1, INSERT_MODE)); + + sq_ctxt->rsvd0 =3D 0; + + sq_ctxt->pref_cache =3D + cpu_to_le32(SQ_CTXT_PREF_SET(SQ_WQ_PREFETCH_MIN, CACHE_MIN) | + SQ_CTXT_PREF_SET(SQ_WQ_PREFETCH_MAX, CACHE_MAX) | + SQ_CTXT_PREF_SET(SQ_WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD)); + + sq_ctxt->pref_ci_owner =3D + cpu_to_le32(SQ_CTXT_PREF_SET(SQ_CTXT_PREF_CI_HI(ci_start), CI_HI) | + SQ_CTXT_PREF_SET(1, OWNER)); + + sq_ctxt->pref_wq_pfn_hi_ci =3D + cpu_to_le32(SQ_CTXT_PREF_SET(ci_start, CI_LOW) | + SQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI)); + + sq_ctxt->pref_wq_pfn_lo =3D cpu_to_le32(wq_page_pfn_lo); + + sq_ctxt->wq_block_pfn_hi =3D + cpu_to_le32(SQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI)); + + sq_ctxt->wq_block_pfn_lo =3D cpu_to_le32(wq_block_pfn_lo); +} + +static void hinic3_rq_prepare_ctxt_get_wq_info(struct hinic3_io_queue *rq, + u32 *wq_page_pfn_hi, + u32 *wq_page_pfn_lo, + u32 *wq_block_pfn_hi, + u32 *wq_block_pfn_lo) +{ + u64 wq_page_addr, wq_page_pfn, wq_block_pfn; + + wq_page_addr =3D hinic3_wq_get_first_wqe_page_addr(&rq->wq); + + wq_page_pfn =3D WQ_PAGE_PFN(wq_page_addr); + *wq_page_pfn_hi =3D upper_32_bits(wq_page_pfn); + *wq_page_pfn_lo =3D lower_32_bits(wq_page_pfn); + + wq_block_pfn =3D WQ_BLOCK_PFN(rq->wq.wq_block_paddr); + *wq_block_pfn_hi =3D upper_32_bits(wq_block_pfn); + *wq_block_pfn_lo =3D lower_32_bits(wq_block_pfn); +} + +static void hinic3_rq_prepare_ctxt(struct hinic3_io_queue *rq, + struct hinic3_rq_ctxt *rq_ctxt) +{ + u32 wq_block_pfn_hi, wq_block_pfn_lo; + u32 wq_page_pfn_hi, wq_page_pfn_lo; + u16 pi_start, ci_start; + + ci_start =3D (rq->wq.cons_idx & rq->wq.idx_mask) << HINIC3_NORMAL_RQ_WQE; + pi_start =3D (rq->wq.prod_idx & rq->wq.idx_mask) << HINIC3_NORMAL_RQ_WQE; + + hinic3_rq_prepare_ctxt_get_wq_info(rq, &wq_page_pfn_hi, &wq_page_pfn_lo, + &wq_block_pfn_hi, &wq_block_pfn_lo); + + rq_ctxt->ci_pi =3D + cpu_to_le32(RQ_CTXT_CI_PI_SET(ci_start, CI_IDX) | + RQ_CTXT_CI_PI_SET(pi_start, PI_IDX)); + + rq_ctxt->ceq_attr =3D + cpu_to_le32(RQ_CTXT_CEQ_ATTR_SET(0, EN) | + RQ_CTXT_CEQ_ATTR_SET(rq->msix_entry_idx, INTR)); + + rq_ctxt->wq_pfn_hi_type_owner =3D + cpu_to_le32(RQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) | + RQ_CTXT_WQ_PAGE_SET(1, OWNER)); + + /* use 16Byte WQE */ + rq_ctxt->wq_pfn_hi_type_owner |=3D + cpu_to_le32(RQ_CTXT_WQ_PAGE_SET(2, WQE_TYPE)); + rq_ctxt->cqe_sge_len =3D cpu_to_le32(RQ_CTXT_CQE_LEN_SET(1, CQE_LEN)); + + rq_ctxt->wq_pfn_lo =3D cpu_to_le32(wq_page_pfn_lo); + + rq_ctxt->pref_cache =3D + cpu_to_le32(RQ_CTXT_PREF_SET(RQ_WQ_PREFETCH_MIN, CACHE_MIN) | + RQ_CTXT_PREF_SET(RQ_WQ_PREFETCH_MAX, CACHE_MAX) | + RQ_CTXT_PREF_SET(RQ_WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD)); + + rq_ctxt->pref_ci_owner =3D + cpu_to_le32(RQ_CTXT_PREF_SET(SQ_CTXT_PREF_CI_HI(ci_start), CI_HI) | + RQ_CTXT_PREF_SET(1, OWNER)); + + rq_ctxt->pref_wq_pfn_hi_ci =3D + cpu_to_le32(RQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI) | + RQ_CTXT_PREF_SET(ci_start, CI_LOW)); + + rq_ctxt->pref_wq_pfn_lo =3D cpu_to_le32(wq_page_pfn_lo); + + rq_ctxt->wq_block_pfn_hi =3D + cpu_to_le32(RQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI)); + + rq_ctxt->wq_block_pfn_lo =3D cpu_to_le32(wq_block_pfn_lo); +} + +static int init_sq_ctxts(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_sq_ctxt_block *sq_ctxt_block; + u16 q_id, curr_id, max_ctxts, i; + struct hinic3_sq_ctxt *sq_ctxt; + struct hinic3_cmd_buf *cmd_buf; + struct hinic3_io_queue *sq; + __le64 out_param; + int err =3D 0; + + cmd_buf =3D hinic3_alloc_cmd_buf(hwdev); + if (!cmd_buf) { + dev_err(hwdev->dev, "Failed to allocate cmd buf\n"); + return -ENOMEM; + } + + q_id =3D 0; + while (q_id < nic_io->num_qps) { + sq_ctxt_block =3D cmd_buf->buf; + sq_ctxt =3D sq_ctxt_block->sq_ctxt; + + max_ctxts =3D (nic_io->num_qps - q_id) > HINIC3_Q_CTXT_MAX ? + HINIC3_Q_CTXT_MAX : (nic_io->num_qps - q_id); + + hinic3_qp_prepare_cmdq_header(&sq_ctxt_block->cmdq_hdr, + HINIC3_QP_CTXT_TYPE_SQ, max_ctxts, + q_id); + + for (i =3D 0; i < max_ctxts; i++) { + curr_id =3D q_id + i; + sq =3D &nic_io->sq[curr_id]; + hinic3_sq_prepare_ctxt(sq, curr_id, &sq_ctxt[i]); + } + + hinic3_cmdq_buf_swab32(sq_ctxt_block, sizeof(*sq_ctxt_block)); + + cmd_buf->size =3D cpu_to_le16(SQ_CTXT_SIZE(max_ctxts)); + err =3D hinic3_cmdq_direct_resp(hwdev, MGMT_MOD_L2NIC, + L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX, + cmd_buf, &out_param); + if (err || out_param) { + dev_err(hwdev->dev, "Failed to set SQ ctxts, err: %d, out_param: 0x%llx= \n", + err, out_param); + err =3D -EFAULT; + break; + } + + q_id +=3D max_ctxts; + } + + hinic3_free_cmd_buf(hwdev, cmd_buf); + + return err; +} + +static int init_rq_ctxts(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_rq_ctxt_block *rq_ctxt_block; + u16 q_id, curr_id, max_ctxts, i; + struct hinic3_rq_ctxt *rq_ctxt; + struct hinic3_cmd_buf *cmd_buf; + struct hinic3_io_queue *rq; + __le64 out_param; + int err =3D 0; + + cmd_buf =3D hinic3_alloc_cmd_buf(hwdev); + if (!cmd_buf) { + dev_err(hwdev->dev, "Failed to allocate cmd buf\n"); + return -ENOMEM; + } + + q_id =3D 0; + while (q_id < nic_io->num_qps) { + rq_ctxt_block =3D cmd_buf->buf; + rq_ctxt =3D rq_ctxt_block->rq_ctxt; + + max_ctxts =3D (nic_io->num_qps - q_id) > HINIC3_Q_CTXT_MAX ? + HINIC3_Q_CTXT_MAX : (nic_io->num_qps - q_id); + + hinic3_qp_prepare_cmdq_header(&rq_ctxt_block->cmdq_hdr, + HINIC3_QP_CTXT_TYPE_RQ, max_ctxts, + q_id); + + for (i =3D 0; i < max_ctxts; i++) { + curr_id =3D q_id + i; + rq =3D &nic_io->rq[curr_id]; + hinic3_rq_prepare_ctxt(rq, &rq_ctxt[i]); + } + + hinic3_cmdq_buf_swab32(rq_ctxt_block, sizeof(*rq_ctxt_block)); + + cmd_buf->size =3D cpu_to_le16(RQ_CTXT_SIZE(max_ctxts)); + + err =3D hinic3_cmdq_direct_resp(hwdev, MGMT_MOD_L2NIC, + L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX, + cmd_buf, &out_param); + if (err || out_param) { + dev_err(hwdev->dev, "Failed to set RQ ctxts, err: %d, out_param: 0x%llx= \n", + err, out_param); + err =3D -EFAULT; + break; + } + + q_id +=3D max_ctxts; + } + + hinic3_free_cmd_buf(hwdev, cmd_buf); + + return err; +} + +static int init_qp_ctxts(struct hinic3_nic_dev *nic_dev) +{ + int err; + + err =3D init_sq_ctxts(nic_dev); + if (err) + return err; + + err =3D init_rq_ctxts(nic_dev); + if (err) + return err; + + return 0; +} + +static int clean_queue_offload_ctxt(struct hinic3_nic_dev *nic_dev, + enum hinic3_qp_ctxt_type ctxt_type) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_clean_queue_ctxt *ctxt_block; + struct hinic3_cmd_buf *cmd_buf; + __le64 out_param; + int err; + + cmd_buf =3D hinic3_alloc_cmd_buf(hwdev); + if (!cmd_buf) { + dev_err(hwdev->dev, "Failed to allocate cmd buf\n"); + return -ENOMEM; + } + + ctxt_block =3D cmd_buf->buf; + ctxt_block->cmdq_hdr.num_queues =3D cpu_to_le16(nic_io->max_qps); + ctxt_block->cmdq_hdr.queue_type =3D cpu_to_le16(ctxt_type); + ctxt_block->cmdq_hdr.start_qid =3D 0; + ctxt_block->cmdq_hdr.rsvd =3D 0; + ctxt_block->rsvd =3D 0; + + hinic3_cmdq_buf_swab32(ctxt_block, sizeof(*ctxt_block)); + + cmd_buf->size =3D cpu_to_le16(sizeof(*ctxt_block)); + + err =3D hinic3_cmdq_direct_resp(hwdev, MGMT_MOD_L2NIC, + L2NIC_UCODE_CMD_CLEAN_QUEUE_CTX, + cmd_buf, &out_param); + if (err || out_param) { + dev_err(hwdev->dev, "Failed to clean queue offload ctxts, err: %d,out_pa= ram: 0x%llx\n", + err, out_param); + + err =3D -EFAULT; + } + + hinic3_free_cmd_buf(hwdev, cmd_buf); + + return err; +} + +static int clean_qp_offload_ctxt(struct hinic3_nic_dev *nic_dev) +{ + /* clean LRO/TSO context space */ + return (clean_queue_offload_ctxt(nic_dev, HINIC3_QP_CTXT_TYPE_SQ) || + clean_queue_offload_ctxt(nic_dev, HINIC3_QP_CTXT_TYPE_RQ)); +} + +/* init qps ctxt and set sq ci attr and arm all sq */ +int hinic3_init_qp_ctxts(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_sq_attr sq_attr; + u32 rq_depth; + u16 q_id; + int err; + + err =3D init_qp_ctxts(nic_dev); + if (err) { + dev_err(hwdev->dev, "Failed to init QP ctxts\n"); + return err; + } + + /* clean LRO/TSO context space */ + err =3D clean_qp_offload_ctxt(nic_dev); + if (err) { + dev_err(hwdev->dev, "Failed to clean qp offload ctxts\n"); + return err; + } + + rq_depth =3D nic_io->rq[0].wq.q_depth << HINIC3_NORMAL_RQ_WQE; + + err =3D hinic3_set_root_ctxt(hwdev, rq_depth, nic_io->sq[0].wq.q_depth, + nic_io->rx_buf_len); + if (err) { + dev_err(hwdev->dev, "Failed to set root context\n"); + return err; + } + + for (q_id =3D 0; q_id < nic_io->num_qps; q_id++) { + sq_attr.ci_dma_base =3D + HINIC3_CI_PADDR(nic_io->ci_dma_base, q_id) >> 0x2; + sq_attr.pending_limit =3D HINIC3_DEFAULT_TX_CI_PENDING_LIMIT; + sq_attr.coalescing_time =3D HINIC3_DEFAULT_TX_CI_COALESCING_TIME; + sq_attr.intr_en =3D 1; + sq_attr.intr_idx =3D nic_io->sq[q_id].msix_entry_idx; + sq_attr.l2nic_sqn =3D q_id; + sq_attr.dma_attr_off =3D 0; + err =3D hinic3_set_ci_table(hwdev, &sq_attr); + if (err) { + dev_err(hwdev->dev, "Failed to set ci table\n"); + goto err_clean_root_ctxt; + } + } + + return 0; + +err_clean_root_ctxt: + hinic3_clean_root_ctxt(hwdev); + + return err; +} + +void hinic3_free_qp_ctxts(struct hinic3_nic_dev *nic_dev) +{ + hinic3_clean_root_ctxt(nic_dev->hwdev); +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.h index c103095c37ef..12eefabcf1db 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h @@ -139,4 +139,7 @@ void hinic3_init_qps(struct hinic3_nic_dev *nic_dev, void hinic3_uninit_qps(struct hinic3_nic_dev *nic_dev, struct hinic3_dyna_qp_params *qp_params); =20 +int hinic3_init_qp_ctxts(struct hinic3_nic_dev *nic_dev); +void hinic3_free_qp_ctxts(struct hinic3_nic_dev *nic_dev); + #endif --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91A593112DF; Fri, 5 Sep 2025 08:29:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060962; cv=none; b=TMldezOgDu0KNvHAKZACBwn8bEQxQavazJjtgBdSTa4V1mWL1+97dI3/KkZfg4qeVuBilDg/rcUmuMaa6nwFwqUFEZFlbFlLYP59dQ0DXqwMzTsbiN6yDhumXzGtcLeEiaIVm5ojLcs8xH9XhM0dw97sa5t6jT6H1bLZQkb35O0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060962; c=relaxed/simple; bh=1dpY5rrx/KQQ7MFnbktR5mrQt1+y3qjUhCGENSPzb6k=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Py3T7DBj0LJm7urC7yVCyVf+Jf+6XmR50jQ/xEDqhr0cYc/s3dHfaPFpOxaGPMC/ynUcStwyuqfVMwDzFeIhpfY1Ljyj6pYZr2Asf04IW00ZrhlZ+D99NxL8YR6nBrE5pL+8Gl5BCWomS8HywP6uLnJjittB4lhVPbnQj9ESe9Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.44]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4cJ8ZK5798z1R99p; Fri, 5 Sep 2025 16:26:17 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id F079F140279; Fri, 5 Sep 2025 16:29:17 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:16 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 10/14] hinic3: Tx & Rx configuration Date: Fri, 5 Sep 2025 16:28:44 +0800 Message-ID: <72048beed5c95d1c1c7437e57a09ccf2355f2014.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Configure Tx & Rx queue common attributes. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../huawei/hinic3/hinic3_mgmt_interface.h | 15 +++++ .../huawei/hinic3/hinic3_netdev_ops.c | 56 +++++++++++++++- .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 25 ++++++++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 2 + .../net/ethernet/huawei/hinic3/hinic3_rx.c | 64 +++++++++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_rx.h | 2 + .../net/ethernet/huawei/hinic3/hinic3_tx.c | 32 ++++++++++ .../net/ethernet/huawei/hinic3/hinic3_tx.h | 2 + 8 files changed, 197 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/d= rivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index b891290a3d6e..20d37670e133 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -75,6 +75,21 @@ struct l2nic_cmd_force_pkt_drop { u8 rsvd1[3]; }; =20 +struct l2nic_cmd_set_dcb_state { + struct mgmt_msg_head head; + u16 func_id; + /* 0 - get dcb state, 1 - set dcb state */ + u8 op_code; + /* 0 - disable, 1 - enable dcb */ + u8 state; + /* 0 - disable, 1 - enable dcb */ + u8 port_state; + u8 rsvd[7]; +}; + +/* IEEE 802.1Qaz std */ +#define L2NIC_DCB_COS_MAX 0x8 + /* Commands between NIC to fw */ enum l2nic_cmd { /* FUNC CFG */ diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index 2c5c7051e72e..cc0a1c2eb681 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -183,6 +183,47 @@ static void hinic3_free_txrxq_resources(struct net_dev= ice *netdev, q_params->txqs_res =3D NULL; } =20 +static int hinic3_configure_txrxqs(struct net_device *netdev, + struct hinic3_dyna_txrxq_params *q_params) +{ + int err; + + err =3D hinic3_configure_txqs(netdev, q_params->num_qps, + q_params->sq_depth, q_params->txqs_res); + if (err) { + netdev_err(netdev, "Failed to configure txqs\n"); + return err; + } + + err =3D hinic3_configure_rxqs(netdev, q_params->num_qps, + q_params->rq_depth, q_params->rxqs_res); + if (err) { + netdev_err(netdev, "Failed to configure rxqs\n"); + return err; + } + + return 0; +} + +static int hinic3_configure(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err; + + netdev->min_mtu =3D HINIC3_MIN_MTU_SIZE; + netdev->max_mtu =3D HINIC3_MAX_JUMBO_FRAME_SIZE; + err =3D hinic3_set_port_mtu(netdev, netdev->mtu); + if (err) { + netdev_err(netdev, "Failed to set mtu\n"); + return err; + } + + /* Ensure DCB is disabled */ + hinic3_sync_dcb_state(nic_dev->hwdev, 1, 0); + + return 0; +} + static int hinic3_alloc_channel_resources(struct net_device *netdev, struct hinic3_dyna_qp_params *qp_params, struct hinic3_dyna_txrxq_params *trxq_params) @@ -231,14 +272,28 @@ static int hinic3_open_channel(struct net_device *net= dev) return err; } =20 + err =3D hinic3_configure_txrxqs(netdev, &nic_dev->q_params); + if (err) { + netdev_err(netdev, "Failed to configure txrxqs\n"); + goto err_free_qp_ctxts; + } + err =3D hinic3_qps_irq_init(netdev); if (err) { netdev_err(netdev, "Failed to init txrxq irq\n"); goto err_free_qp_ctxts; } =20 + err =3D hinic3_configure(netdev); + if (err) { + netdev_err(netdev, "Failed to init txrxq irq\n"); + goto err_uninit_qps_irq; + } + return 0; =20 +err_uninit_qps_irq: + hinic3_qps_irq_uninit(netdev); err_free_qp_ctxts: hinic3_free_qp_ctxts(nic_dev); =20 @@ -287,7 +342,6 @@ static int hinic3_open(struct net_device *netdev) err_uninit_qps: hinic3_uninit_qps(nic_dev, &qp_params); hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); - err_destroy_num_qps: hinic3_destroy_num_qps(netdev); err_free_nicio_res: diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index 5b18764781d4..ed70750f5ae8 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -289,3 +289,28 @@ int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwde= v) =20 return pkt_drop.msg_head.status; } + +int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state) +{ + struct l2nic_cmd_set_dcb_state dcb_state =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + dcb_state.op_code =3D op_code; + dcb_state.state =3D state; + dcb_state.func_id =3D hinic3_global_func_id(hwdev); + + mgmt_msg_params_init_default(&msg_params, &dcb_state, + sizeof(dcb_state)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_QOS_DCB_STATE, &msg_params); + if (err || dcb_state.head.status) { + dev_err(hwdev->dev, + "Failed to set dcb state, err: %d, status: 0x%x\n", + err, dcb_state.head.status); + return -EFAULT; + } + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.h index dd1615745f02..719b81e2bc2a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h @@ -52,4 +52,6 @@ int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, struct hinic3_sq_attr *attr); int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev); =20 +int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state= ); + #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.c index e81f7c19bf63..6cfe3bdd8ee5 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c @@ -85,6 +85,27 @@ static int rx_alloc_mapped_page(struct page_pool *page_p= ool, return 0; } =20 +/* Associate fixed completion element to every wqe in the rq. Every rq wqe= will + * always post completion to the same place. + */ +static void rq_associate_cqes(struct hinic3_rxq *rxq) +{ + struct hinic3_queue_pages *qpages; + struct hinic3_rq_wqe *rq_wqe; + dma_addr_t cqe_dma; + u32 i; + + qpages =3D &rxq->rq->wq.qpages; + + for (i =3D 0; i < rxq->q_depth; i++) { + rq_wqe =3D get_q_element(qpages, i, NULL); + cqe_dma =3D rxq->cqe_start_paddr + + i * sizeof(struct hinic3_rq_cqe); + rq_wqe->cqe_hi_addr =3D cpu_to_le32(upper_32_bits(cqe_dma)); + rq_wqe->cqe_lo_addr =3D cpu_to_le32(lower_32_bits(cqe_dma)); + } +} + static void rq_wqe_buf_set(struct hinic3_io_queue *rq, uint32_t wqe_idx, dma_addr_t dma_addr, u16 len) { @@ -445,6 +466,49 @@ void hinic3_free_rxqs_res(struct net_device *netdev, u= 16 num_rq, } } =20 +int hinic3_configure_rxqs(struct net_device *netdev, u16 num_rq, + u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_dyna_rxq_res *rqres; + struct msix_entry *msix_entry; + struct hinic3_rxq *rxq; + u16 q_id; + u32 pkts; + + for (q_id =3D 0; q_id < num_rq; q_id++) { + rxq =3D &nic_dev->rxqs[q_id]; + rqres =3D &rxqs_res[q_id]; + msix_entry =3D &nic_dev->qps_msix_entries[q_id]; + + rxq->irq_id =3D msix_entry->vector; + rxq->msix_entry_idx =3D msix_entry->entry; + rxq->next_to_update =3D 0; + rxq->next_to_alloc =3D rqres->next_to_alloc; + rxq->q_depth =3D rq_depth; + rxq->delta =3D rxq->q_depth; + rxq->q_mask =3D rxq->q_depth - 1; + rxq->cons_idx =3D 0; + + rxq->cqe_arr =3D rqres->cqe_start_vaddr; + rxq->cqe_start_paddr =3D rqres->cqe_start_paddr; + rxq->rx_info =3D rqres->rx_info; + rxq->page_pool =3D rqres->page_pool; + + rxq->rq =3D &nic_dev->nic_io->rq[rxq->q_id]; + + rq_associate_cqes(rxq); + + pkts =3D hinic3_rx_fill_buffers(rxq); + if (!pkts) { + netdev_err(netdev, "Failed to fill Rx buffer\n"); + return -ENOMEM; + } + } + + return 0; +} + int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(rxq->netdev); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.h index ec3f45c3688a..44ae841a3648 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h @@ -97,6 +97,8 @@ int hinic3_alloc_rxqs_res(struct net_device *netdev, u16 = num_rq, u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res); void hinic3_free_rxqs_res(struct net_device *netdev, u16 num_rq, u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res); +int hinic3_configure_rxqs(struct net_device *netdev, u16 num_rq, + u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res); int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.c index 3c63fe071999..dea882260b11 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c @@ -702,6 +702,38 @@ void hinic3_free_txqs_res(struct net_device *netdev, u= 16 num_sq, } } =20 +int hinic3_configure_txqs(struct net_device *netdev, u16 num_sq, + u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_dyna_txq_res *tqres; + struct hinic3_txq *txq; + u16 q_id; + u32 idx; + + for (q_id =3D 0; q_id < num_sq; q_id++) { + txq =3D &nic_dev->txqs[q_id]; + tqres =3D &txqs_res[q_id]; + + txq->q_depth =3D sq_depth; + txq->q_mask =3D sq_depth - 1; + + txq->tx_stop_thrs =3D min(HINIC3_DEFAULT_STOP_THRS, + sq_depth / 20); + txq->tx_start_thrs =3D min(HINIC3_DEFAULT_START_THRS, + sq_depth / 10); + + txq->tx_info =3D tqres->tx_info; + for (idx =3D 0; idx < sq_depth; idx++) + txq->tx_info[idx].dma_info =3D + &tqres->bds[idx * HINIC3_BDS_PER_SQ_WQEBB]; + + txq->sq =3D &nic_dev->nic_io->sq[q_id]; + } + + return 0; +} + bool hinic3_tx_poll(struct hinic3_txq *txq, int budget) { struct net_device *netdev =3D txq->netdev; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.h index 9ec6968b6688..7e1b872ba752 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h @@ -137,6 +137,8 @@ int hinic3_alloc_txqs_res(struct net_device *netdev, u1= 6 num_sq, u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res); void hinic3_free_txqs_res(struct net_device *netdev, u16 num_sq, u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res); +int hinic3_configure_txqs(struct net_device *netdev, u16 num_sq, + u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res); =20 netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, struct net_device *netd= ev); bool hinic3_tx_poll(struct hinic3_txq *txq, int budget); --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga06-in.huawei.com (szxga06-in.huawei.com [45.249.212.32]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC45A3054FF; Fri, 5 Sep 2025 08:29:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.32 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060965; cv=none; b=crh+tzz3k/Mb7Dq0HQu8d+jmMO+4Uj8Fz+E9LvWVzZRA7fR2EXdxWvCG5YEq06g7L62YlmZCIO6WYfIQq3lmBWti3nb450F12Cg/Bf73IaIcjo3cDnd9tGwh0zpMmrOu0YgKTqZIg/OsgiS7gCqPs7FyFsHIvawsK3QHqmVRD/A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060965; c=relaxed/simple; bh=xDLG8fRmGQBHQ2AumwI/05RRBUUNXdcvtlSaoKaE7GI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lmsx2YR/NovSSac0uLyQ3zaUhYy0GBmdMnsTFWn7ZNAg/MSFLgzRAOgRSoMZHOjlVxK5eMeUyrjTGsoDjSxHI1FHOfw55fwOWSy+d0rx+FmoSUNK1OKWteJWkWpaHeqqFfU6bWAZkMJJHqIa+Gg7vbRd982VCt2BujB+ppxheac= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.32 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.234]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4cJ8g82Vqrz3tZWF; Fri, 5 Sep 2025 16:30:28 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 23C8B14027A; Fri, 5 Sep 2025 16:29:20 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:18 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 11/14] hinic3: Add Rss function Date: Fri, 5 Sep 2025 16:28:45 +0800 Message-ID: <3283442615fea03ef9d89ce743db643860ecc69c.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Initialize rss functions. Configure rss hash data and HW resources. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- drivers/net/ethernet/huawei/hinic3/Makefile | 1 + .../net/ethernet/huawei/hinic3/hinic3_main.c | 8 +- .../huawei/hinic3/hinic3_mgmt_interface.h | 55 +++ .../huawei/hinic3/hinic3_netdev_ops.c | 18 + .../ethernet/huawei/hinic3/hinic3_nic_dev.h | 5 + .../net/ethernet/huawei/hinic3/hinic3_rss.c | 336 ++++++++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_rss.h | 14 + 7 files changed, 436 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic3/Makefile b/drivers/net/ethe= rnet/huawei/hinic3/Makefile index a9f055cfef52..c3efa45a6a42 100644 --- a/drivers/net/ethernet/huawei/hinic3/Makefile +++ b/drivers/net/ethernet/huawei/hinic3/Makefile @@ -19,6 +19,7 @@ hinic3-objs :=3D hinic3_cmdq.o \ hinic3_nic_cfg.o \ hinic3_nic_io.o \ hinic3_queue_common.o \ + hinic3_rss.o \ hinic3_rx.o \ hinic3_tx.o \ hinic3_wq.o diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_main.c index a0b04fb07c76..6d87d4d895ba 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c @@ -12,6 +12,7 @@ #include "hinic3_nic_cfg.h" #include "hinic3_nic_dev.h" #include "hinic3_nic_io.h" +#include "hinic3_rss.h" #include "hinic3_rx.h" #include "hinic3_tx.h" =20 @@ -134,6 +135,8 @@ static int hinic3_sw_init(struct net_device *netdev) nic_dev->q_params.sq_depth =3D HINIC3_SQ_DEPTH; nic_dev->q_params.rq_depth =3D HINIC3_RQ_DEPTH; =20 + hinic3_try_to_enable_rss(netdev); + /* VF driver always uses random MAC address. During VM migration to a * new device, the new device should learn the VMs old MAC rather than * provide its own MAC. The product design assumes that every VF is @@ -145,7 +148,7 @@ static int hinic3_sw_init(struct net_device *netdev) hinic3_global_func_id(hwdev)); if (err) { dev_err(hwdev->dev, "Failed to set default MAC\n"); - return err; + goto err_clear_rss_config; } =20 err =3D hinic3_alloc_txrxqs(netdev); @@ -159,6 +162,8 @@ static int hinic3_sw_init(struct net_device *netdev) err_del_mac: hinic3_del_mac(hwdev, netdev->dev_addr, 0, hinic3_global_func_id(hwdev)); +err_clear_rss_config: + hinic3_clear_rss_config(netdev); =20 return err; } @@ -170,6 +175,7 @@ static void hinic3_sw_uninit(struct net_device *netdev) hinic3_free_txrxqs(netdev); hinic3_del_mac(nic_dev->hwdev, netdev->dev_addr, 0, hinic3_global_func_id(nic_dev->hwdev)); + hinic3_clear_rss_config(netdev); } =20 static void hinic3_assign_netdev_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/d= rivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index 20d37670e133..7012130bba1d 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -87,9 +87,59 @@ struct l2nic_cmd_set_dcb_state { u8 rsvd[7]; }; =20 +#define L2NIC_RSS_TYPE_VALID_MASK BIT(23) +#define L2NIC_RSS_TYPE_TCP_IPV6_EXT_MASK BIT(24) +#define L2NIC_RSS_TYPE_IPV6_EXT_MASK BIT(25) +#define L2NIC_RSS_TYPE_TCP_IPV6_MASK BIT(26) +#define L2NIC_RSS_TYPE_IPV6_MASK BIT(27) +#define L2NIC_RSS_TYPE_TCP_IPV4_MASK BIT(28) +#define L2NIC_RSS_TYPE_IPV4_MASK BIT(29) +#define L2NIC_RSS_TYPE_UDP_IPV6_MASK BIT(30) +#define L2NIC_RSS_TYPE_UDP_IPV4_MASK BIT(31) +#define L2NIC_RSS_TYPE_SET(val, member) \ + FIELD_PREP(L2NIC_RSS_TYPE_##member##_MASK, val) +#define L2NIC_RSS_TYPE_GET(val, member) \ + FIELD_GET(L2NIC_RSS_TYPE_##member##_MASK, val) + +#define L2NIC_RSS_INDIR_SIZE 256 +#define L2NIC_RSS_KEY_SIZE 40 + /* IEEE 802.1Qaz std */ #define L2NIC_DCB_COS_MAX 0x8 =20 +struct l2nic_cmd_set_rss_ctx_tbl { + struct mgmt_msg_head msg_head; + u16 func_id; + u16 rsvd1; + u32 context; +}; + +struct l2nic_cmd_cfg_rss_engine { + struct mgmt_msg_head msg_head; + u16 func_id; + u8 opcode; + u8 hash_engine; + u8 rsvd1[4]; +}; + +struct l2nic_cmd_cfg_rss_hash_key { + struct mgmt_msg_head msg_head; + u16 func_id; + u8 opcode; + u8 rsvd1; + u8 key[L2NIC_RSS_KEY_SIZE]; +}; + +struct l2nic_cmd_cfg_rss { + struct mgmt_msg_head msg_head; + u16 func_id; + u8 rss_en; + u8 rq_priority_number; + u8 prio_tc[L2NIC_DCB_COS_MAX]; + u16 num_qps; + u16 rsvd1; +}; + /* Commands between NIC to fw */ enum l2nic_cmd { /* FUNC CFG */ @@ -110,6 +160,11 @@ enum l2nic_cmd { L2NIC_CMD_MAX =3D 256, }; =20 +struct l2nic_cmd_rss_set_indir_tbl { + __le32 rsvd[4]; + __le16 entry[L2NIC_RSS_INDIR_SIZE]; +}; + /* NIC CMDQ MODE */ enum l2nic_ucode_cmd { L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX =3D 0, diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index cc0a1c2eb681..3d17ca5e7ba5 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -8,6 +8,7 @@ #include "hinic3_nic_cfg.h" #include "hinic3_nic_dev.h" #include "hinic3_nic_io.h" +#include "hinic3_rss.h" #include "hinic3_rx.h" #include "hinic3_tx.h" =20 @@ -221,9 +222,25 @@ static int hinic3_configure(struct net_device *netdev) /* Ensure DCB is disabled */ hinic3_sync_dcb_state(nic_dev->hwdev, 1, 0); =20 + if (test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) { + err =3D hinic3_rss_init(netdev); + if (err) { + netdev_err(netdev, "Failed to init rss\n"); + return err; + } + } + return 0; } =20 +static void hinic3_remove_configure(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + if (test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) + hinic3_rss_uninit(netdev); +} + static int hinic3_alloc_channel_resources(struct net_device *netdev, struct hinic3_dyna_qp_params *qp_params, struct hinic3_dyna_txrxq_params *trxq_params) @@ -304,6 +321,7 @@ static void hinic3_close_channel(struct net_device *net= dev) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); =20 + hinic3_remove_configure(netdev); hinic3_qps_irq_uninit(netdev); hinic3_free_qp_ctxts(nic_dev); } diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_dev.h index 9fad834f9e92..5ba83261616c 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h @@ -73,6 +73,11 @@ struct hinic3_nic_dev { struct hinic3_txq *txqs; struct hinic3_rxq *rxqs; =20 + enum hinic3_rss_hash_type rss_hash_type; + struct hinic3_rss_type rss_type; + u8 *rss_hkey; + u16 *rss_indir; + u16 num_qp_irq; struct msix_entry *qps_msix_entries; =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_rss.c new file mode 100644 index 000000000000..4ff1b2f79838 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c @@ -0,0 +1,336 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + +#include + +#include "hinic3_cmdq.h" +#include "hinic3_hwdev.h" +#include "hinic3_hwif.h" +#include "hinic3_mbox.h" +#include "hinic3_nic_cfg.h" +#include "hinic3_nic_dev.h" +#include "hinic3_rss.h" + +static void hinic3_fillout_indir_tbl(struct net_device *netdev, u16 *indir) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u16 i, num_qps; + + num_qps =3D nic_dev->q_params.num_qps; + for (i =3D 0; i < L2NIC_RSS_INDIR_SIZE; i++) + indir[i] =3D ethtool_rxfh_indir_default(i, num_qps); +} + +static int hinic3_rss_cfg(struct hinic3_hwdev *hwdev, u8 rss_en, u16 num_q= ps) +{ + struct mgmt_msg_params msg_params =3D {}; + struct l2nic_cmd_cfg_rss rss_cfg =3D {}; + int err; + + rss_cfg.func_id =3D hinic3_global_func_id(hwdev); + rss_cfg.rss_en =3D rss_en; + rss_cfg.rq_priority_number =3D 0; + rss_cfg.num_qps =3D num_qps; + + mgmt_msg_params_init_default(&msg_params, &rss_cfg, sizeof(rss_cfg)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_CFG_RSS, &msg_params); + if (err || rss_cfg.msg_head.status) { + dev_err(hwdev->dev, "Failed to set rss cfg, err: %d, status: 0x%x\n", + err, rss_cfg.msg_head.status); + return -EINVAL; + } + + return 0; +} + +static void hinic3_init_rss_parameters(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + nic_dev->rss_hash_type =3D HINIC3_RSS_HASH_ENGINE_TYPE_XOR; + nic_dev->rss_type.tcp_ipv6_ext =3D 1; + nic_dev->rss_type.ipv6_ext =3D 1; + nic_dev->rss_type.tcp_ipv6 =3D 1; + nic_dev->rss_type.ipv6 =3D 1; + nic_dev->rss_type.tcp_ipv4 =3D 1; + nic_dev->rss_type.ipv4 =3D 1; + nic_dev->rss_type.udp_ipv6 =3D 1; + nic_dev->rss_type.udp_ipv4 =3D 1; +} + +static void decide_num_qps(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + unsigned int dev_cpus; + + dev_cpus =3D netif_get_num_default_rss_queues(); + nic_dev->q_params.num_qps =3D min(dev_cpus, nic_dev->max_qps); +} + +static int alloc_rss_resource(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + nic_dev->rss_hkey =3D kmalloc_array(L2NIC_RSS_KEY_SIZE, + sizeof(nic_dev->rss_hkey[0]), + GFP_KERNEL); + if (!nic_dev->rss_hkey) + return -ENOMEM; + + netdev_rss_key_fill(nic_dev->rss_hkey, L2NIC_RSS_KEY_SIZE); + + nic_dev->rss_indir =3D kcalloc(L2NIC_RSS_INDIR_SIZE, sizeof(u16), + GFP_KERNEL); + if (!nic_dev->rss_indir) { + kfree(nic_dev->rss_hkey); + nic_dev->rss_hkey =3D NULL; + return -ENOMEM; + } + + return 0; +} + +static int hinic3_rss_set_indir_tbl(struct hinic3_hwdev *hwdev, + const u16 *indir_table) +{ + struct l2nic_cmd_rss_set_indir_tbl *indir_tbl; + struct hinic3_cmd_buf *cmd_buf; + __le64 out_param; + int err; + u32 i; + + cmd_buf =3D hinic3_alloc_cmd_buf(hwdev); + if (!cmd_buf) { + dev_err(hwdev->dev, "Failed to allocate cmd buf\n"); + return -ENOMEM; + } + + cmd_buf->size =3D cpu_to_le16(sizeof(struct l2nic_cmd_rss_set_indir_tbl)); + indir_tbl =3D cmd_buf->buf; + memset(indir_tbl, 0, sizeof(*indir_tbl)); + + for (i =3D 0; i < L2NIC_RSS_INDIR_SIZE; i++) + indir_tbl->entry[i] =3D cpu_to_le16(indir_table[i]); + + hinic3_cmdq_buf_swab32(indir_tbl, sizeof(*indir_tbl)); + + err =3D hinic3_cmdq_direct_resp(hwdev, MGMT_MOD_L2NIC, + L2NIC_UCODE_CMD_SET_RSS_INDIR_TBL, + cmd_buf, &out_param); + if (err || out_param) { + dev_err(hwdev->dev, "Failed to set rss indir table\n"); + err =3D -EFAULT; + } + + hinic3_free_cmd_buf(hwdev, cmd_buf); + + return err; +} + +static int hinic3_set_rss_type(struct hinic3_hwdev *hwdev, + struct hinic3_rss_type rss_type) +{ + struct l2nic_cmd_set_rss_ctx_tbl ctx_tbl =3D {}; + struct mgmt_msg_params msg_params =3D {}; + u32 ctx; + int err; + + ctx_tbl.func_id =3D hinic3_global_func_id(hwdev); + ctx =3D L2NIC_RSS_TYPE_SET(1, VALID) | + L2NIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) | + L2NIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) | + L2NIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) | + L2NIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) | + L2NIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) | + L2NIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) | + L2NIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) | + L2NIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6); + ctx_tbl.context =3D ctx; + + mgmt_msg_params_init_default(&msg_params, &ctx_tbl, sizeof(ctx_tbl)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_SET_RSS_CTX_TBL, &msg_params); + + if (ctx_tbl.msg_head.status =3D=3D MGMT_STATUS_CMD_UNSUPPORTED) { + return MGMT_STATUS_CMD_UNSUPPORTED; + } else if (err || ctx_tbl.msg_head.status) { + dev_err(hwdev->dev, "mgmt Failed to set rss context offload, err: %d, st= atus: 0x%x\n", + err, ctx_tbl.msg_head.status); + return -EINVAL; + } + + return 0; +} + +static int hinic3_rss_cfg_hash_type(struct hinic3_hwdev *hwdev, u8 opcode, + enum hinic3_rss_hash_type *type) +{ + struct l2nic_cmd_cfg_rss_engine hash_type_cmd =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + hash_type_cmd.func_id =3D hinic3_global_func_id(hwdev); + hash_type_cmd.opcode =3D opcode; + + if (opcode =3D=3D MGMT_MSG_CMD_OP_SET) + hash_type_cmd.hash_engine =3D *type; + + mgmt_msg_params_init_default(&msg_params, &hash_type_cmd, + sizeof(hash_type_cmd)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_CFG_RSS_HASH_ENGINE, + &msg_params); + if (err || hash_type_cmd.msg_head.status) { + dev_err(hwdev->dev, "Failed to %s hash engine, err: %d, status: 0x%x\n", + opcode =3D=3D MGMT_MSG_CMD_OP_SET ? "set" : "get", + err, hash_type_cmd.msg_head.status); + return -EIO; + } + + if (opcode =3D=3D MGMT_MSG_CMD_OP_GET) + *type =3D hash_type_cmd.hash_engine; + + return 0; +} + +static int hinic3_rss_set_hash_type(struct hinic3_hwdev *hwdev, + enum hinic3_rss_hash_type type) +{ + return hinic3_rss_cfg_hash_type(hwdev, MGMT_MSG_CMD_OP_SET, &type); +} + +static int hinic3_config_rss_hw_resource(struct net_device *netdev, + u16 *indir_tbl) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err; + + err =3D hinic3_rss_set_indir_tbl(nic_dev->hwdev, indir_tbl); + if (err) + return err; + + err =3D hinic3_set_rss_type(nic_dev->hwdev, nic_dev->rss_type); + if (err) + return err; + + return hinic3_rss_set_hash_type(nic_dev->hwdev, nic_dev->rss_hash_type); +} + +static int hinic3_rss_cfg_hash_key(struct hinic3_hwdev *hwdev, u8 opcode, + u8 *key) +{ + struct l2nic_cmd_cfg_rss_hash_key hash_key =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + hash_key.func_id =3D hinic3_global_func_id(hwdev); + hash_key.opcode =3D opcode; + + if (opcode =3D=3D MGMT_MSG_CMD_OP_SET) + memcpy(hash_key.key, key, L2NIC_RSS_KEY_SIZE); + + mgmt_msg_params_init_default(&msg_params, &hash_key, sizeof(hash_key)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_CFG_RSS_HASH_KEY, &msg_params); + if (err || hash_key.msg_head.status) { + dev_err(hwdev->dev, "Failed to %s hash key, err: %d, status: 0x%x\n", + opcode =3D=3D MGMT_MSG_CMD_OP_SET ? "set" : "get", + err, hash_key.msg_head.status); + return -EINVAL; + } + + if (opcode =3D=3D MGMT_MSG_CMD_OP_GET) + memcpy(key, hash_key.key, L2NIC_RSS_KEY_SIZE); + + return 0; +} + +static int hinic3_rss_set_hash_key(struct hinic3_hwdev *hwdev, u8 *key) +{ + return hinic3_rss_cfg_hash_key(hwdev, MGMT_MSG_CMD_OP_SET, key); +} + +static int hinic3_set_hw_rss_parameters(struct net_device *netdev, u8 rss_= en) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err; + + err =3D hinic3_rss_set_hash_key(nic_dev->hwdev, nic_dev->rss_hkey); + if (err) + return err; + + hinic3_fillout_indir_tbl(netdev, nic_dev->rss_indir); + + err =3D hinic3_config_rss_hw_resource(netdev, nic_dev->rss_indir); + if (err) + return err; + + err =3D hinic3_rss_cfg(nic_dev->hwdev, rss_en, nic_dev->q_params.num_qps); + if (err) + return err; + + return 0; +} + +int hinic3_rss_init(struct net_device *netdev) +{ + return hinic3_set_hw_rss_parameters(netdev, 1); +} + +void hinic3_rss_uninit(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + hinic3_rss_cfg(nic_dev->hwdev, 0, 0); +} + +void hinic3_clear_rss_config(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + kfree(nic_dev->rss_hkey); + nic_dev->rss_hkey =3D NULL; + + kfree(nic_dev->rss_indir); + nic_dev->rss_indir =3D NULL; +} + +void hinic3_try_to_enable_rss(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + int err; + + nic_dev->max_qps =3D hinic3_func_max_qnum(hwdev); + if (nic_dev->max_qps <=3D 1 || + !hinic3_test_support(nic_dev, HINIC3_NIC_F_RSS)) + goto err_reset_q_params; + + err =3D alloc_rss_resource(netdev); + if (err) { + nic_dev->max_qps =3D 1; + goto err_reset_q_params; + } + + set_bit(HINIC3_RSS_ENABLE, &nic_dev->flags); + decide_num_qps(netdev); + hinic3_init_rss_parameters(netdev); + err =3D hinic3_set_hw_rss_parameters(netdev, 0); + if (err) { + dev_err(hwdev->dev, "Failed to set hardware rss parameters\n"); + hinic3_clear_rss_config(netdev); + nic_dev->max_qps =3D 1; + goto err_reset_q_params; + } + + return; + +err_reset_q_params: + clear_bit(HINIC3_RSS_ENABLE, &nic_dev->flags); + nic_dev->q_params.num_qps =3D nic_dev->max_qps; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.h b/drivers/net/= ethernet/huawei/hinic3/hinic3_rss.h new file mode 100644 index 000000000000..78d82c2aca06 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. = */ + +#ifndef _HINIC3_RSS_H_ +#define _HINIC3_RSS_H_ + +#include + +int hinic3_rss_init(struct net_device *netdev); +void hinic3_rss_uninit(struct net_device *netdev); +void hinic3_try_to_enable_rss(struct net_device *netdev); +void hinic3_clear_rss_config(struct net_device *netdev); + +#endif --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B0193128B1; Fri, 5 Sep 2025 08:29:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060967; cv=none; b=pl2za5RHe68abAf7Srd8HVvJXd35pbgMwr1henKEchw4Qvj4dio1q7LN2IfDDe2vsFC4rrB91Lx+L7itYXQHdOkG6Cex6bRCY+tDj/bmlOVQjwAfQSmZTxvDtddwCudzQLkXsXoQk0x41yZ2U94uczdbCxUrCOHv0e93GsCRajg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060967; c=relaxed/simple; bh=yF0bX13QiU9YmKsN+BFkUljpXOCWRF+Go0TMI2Xm9Dg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jLrXqT9x9CKrWw/kqklI1JKcWMJht/5RMNU8kxnDaeKK3mrQsiA8C6vm90VWxfo6jAc5NcQpUu10YfUA+JGajIuknhLrnWKtw9PoYQU1jb5e2A0xJxKmYynEZY8AGvm5ALJw7K+ciXY8+zbSSF83aOETHddViH8MyZFFLJM5Egw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.162.112]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4cJ8ZF3X53z24j1W; Fri, 5 Sep 2025 16:26:13 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 7B15614022E; Fri, 5 Sep 2025 16:29:22 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:20 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 12/14] hinic3: Add port management Date: Fri, 5 Sep 2025 16:28:46 +0800 Message-ID: <61085ba697c082469af9159e01cccaf0c44efd95.1757057860.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Add port management of enable/disable/query/flush function. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../huawei/hinic3/hinic3_mgmt_interface.h | 29 ++++++++ .../huawei/hinic3/hinic3_netdev_ops.c | 60 ++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 68 +++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 4 ++ 4 files changed, 161 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/d= rivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index 7012130bba1d..6cc0345c39e4 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -69,12 +69,27 @@ struct l2nic_cmd_set_ci_attr { u64 ci_addr; }; =20 +struct l2nic_cmd_clear_qp_resource { + struct mgmt_msg_head msg_head; + u16 func_id; + u16 rsvd1; +}; + struct l2nic_cmd_force_pkt_drop { struct mgmt_msg_head msg_head; u8 port; u8 rsvd1[3]; }; =20 +struct l2nic_cmd_set_vport_state { + struct mgmt_msg_head msg_head; + u16 func_id; + u16 rsvd1; + /* 0--disable, 1--enable */ + u8 state; + u8 rsvd2[3]; +}; + struct l2nic_cmd_set_dcb_state { struct mgmt_msg_head head; u16 func_id; @@ -172,6 +187,20 @@ enum l2nic_ucode_cmd { L2NIC_UCODE_CMD_SET_RSS_INDIR_TBL =3D 4, }; =20 +/* hilink mac group command */ +enum mag_cmd { + MAG_CMD_GET_LINK_STATUS =3D 7, +}; + +/* firmware also use this cmd report link event to driver */ +struct mag_cmd_get_link_status { + struct mgmt_msg_head head; + u8 port_id; + /* 0:link down 1:link up */ + u8 status; + u8 rsvd0[2]; +}; + enum hinic3_nic_feature_cap { HINIC3_NIC_F_CSUM =3D BIT(0), HINIC3_NIC_F_SCTP_CRC =3D BIT(1), diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index 3d17ca5e7ba5..a07fa4bd71e7 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -326,6 +326,59 @@ static void hinic3_close_channel(struct net_device *ne= tdev) hinic3_free_qp_ctxts(nic_dev); } =20 +static int hinic3_vport_up(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + bool link_status_up; + u16 glb_func_id; + int err; + + glb_func_id =3D hinic3_global_func_id(nic_dev->hwdev); + err =3D hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, true); + if (err) { + netdev_err(netdev, "Failed to enable vport\n"); + goto err_flush_qps_res; + } + + err =3D netif_set_real_num_queues(netdev, nic_dev->q_params.num_qps, + nic_dev->q_params.num_qps); + if (err) { + netdev_err(netdev, "Failed to set real number of queues\n"); + goto err_flush_qps_res; + } + netif_tx_start_all_queues(netdev); + + err =3D hinic3_get_link_status(nic_dev->hwdev, &link_status_up); + if (!err && link_status_up) + netif_carrier_on(netdev); + + return 0; + +err_flush_qps_res: + hinic3_flush_qps_res(nic_dev->hwdev); + /* wait to guarantee that no packets will be sent to host */ + msleep(100); + + return err; +} + +static void hinic3_vport_down(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u16 glb_func_id; + + netif_carrier_off(netdev); + netif_tx_disable(netdev); + + glb_func_id =3D hinic3_global_func_id(nic_dev->hwdev); + hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false); + + hinic3_flush_txqs(netdev); + /* wait to guarantee that no packets will be sent to host */ + msleep(100); + hinic3_flush_qps_res(nic_dev->hwdev); +} + static int hinic3_open(struct net_device *netdev) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); @@ -355,8 +408,14 @@ static int hinic3_open(struct net_device *netdev) if (err) goto err_uninit_qps; =20 + err =3D hinic3_vport_up(netdev); + if (err) + goto err_close_channel; + return 0; =20 +err_close_channel: + hinic3_close_channel(netdev); err_uninit_qps: hinic3_uninit_qps(nic_dev, &qp_params); hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); @@ -373,6 +432,7 @@ static int hinic3_close(struct net_device *netdev) struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); struct hinic3_dyna_qp_params qp_params; =20 + hinic3_vport_down(netdev); hinic3_close_channel(netdev); hinic3_uninit_qps(nic_dev, &qp_params); hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index ed70750f5ae8..9349b8a314ae 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -267,6 +267,28 @@ int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, st= ruct hinic3_sq_attr *attr) return 0; } =20 +int hinic3_flush_qps_res(struct hinic3_hwdev *hwdev) +{ + struct l2nic_cmd_clear_qp_resource sq_res =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + sq_res.func_id =3D hinic3_global_func_id(hwdev); + + mgmt_msg_params_init_default(&msg_params, &sq_res, sizeof(sq_res)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_CLEAR_QP_RESOURCE, + &msg_params); + if (err || sq_res.msg_head.status) { + dev_err(hwdev->dev, "Failed to clear sq resources, err: %d, status: 0x%x= \n", + err, sq_res.msg_head.status); + return -EINVAL; + } + + return 0; +} + int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev) { struct l2nic_cmd_force_pkt_drop pkt_drop =3D {}; @@ -314,3 +336,49 @@ int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, = u8 op_code, u8 state) =20 return 0; } + +int hinic3_get_link_status(struct hinic3_hwdev *hwdev, bool *link_status_u= p) +{ + struct mag_cmd_get_link_status get_link =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + get_link.port_id =3D hinic3_physical_port_id(hwdev); + + mgmt_msg_params_init_default(&msg_params, &get_link, sizeof(get_link)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK, + MAG_CMD_GET_LINK_STATUS, &msg_params); + if (err || get_link.head.status) { + dev_err(hwdev->dev, "Failed to get link state, err: %d, status: 0x%x\n", + err, get_link.head.status); + return -EIO; + } + + *link_status_up =3D !!get_link.status; + + return 0; +} + +int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id, + bool enable) +{ + struct l2nic_cmd_set_vport_state en_state =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + en_state.func_id =3D func_id; + en_state.state =3D enable ? 1 : 0; + + mgmt_msg_params_init_default(&msg_params, &en_state, sizeof(en_state)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_SET_VPORT_ENABLE, &msg_params); + if (err || en_state.msg_head.status) { + dev_err(hwdev->dev, "Failed to set vport state, err: %d, status: 0x%x\n", + err, en_state.msg_head.status); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.h index 719b81e2bc2a..b83b567fa542 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h @@ -50,8 +50,12 @@ int hinic3_update_mac(struct hinic3_hwdev *hwdev, const = u8 *old_mac, =20 int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, struct hinic3_sq_attr *attr); +int hinic3_flush_qps_res(struct hinic3_hwdev *hwdev); int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev); =20 int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state= ); +int hinic3_get_link_status(struct hinic3_hwdev *hwdev, bool *link_status_u= p); +int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id, + bool enable); =20 #endif --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 50C00313E2D; Fri, 5 Sep 2025 08:29:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060969; cv=none; b=Zy5IPUyjFutvjvUgDyXapjGrLeXSyIsFEtm+NstUPmDZAcLy88jnPkSBpvn6GxswAzOu4K8NRjeqcECo4CwCDnQxDTHeuRX8oargV74X3VIIa2Ll/d1U//CqnMKcp7pODxy4prg75dpWDRWjzIIwP8r7awPby/CZQT6GxAPhSaQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060969; c=relaxed/simple; bh=ozKXCUJBwA8AGE6G5Ir90RcqESJyy+xuV+ssZVHyZi0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Agm066q8ZkPph/xJk/wH2ie9XJ/6KVBVCnhJjfCCTa7CowRT6z0g5puT/gG7fWTMhNGuCt8RPNDvnaq/nqn9ZANbXXjusT3DtLLoh/dVBQm/TJE2lo53bkZ6r4rhmMnhYE9s4i0U7hd4wKUBtP/cT4eXAKk+fPXj6aukjGKVwsU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.105]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4cJ8YR0VGvz13N77; Fri, 5 Sep 2025 16:25:31 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id E49D9140147; Fri, 5 Sep 2025 16:29:24 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:23 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 13/14] hinic3: Fix missing napi->dev in netif_queue_set_napi Date: Fri, 5 Sep 2025 16:28:47 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" As netif_queue_set_napi checks napi->dev, if it doesn't have it and it will warn_on and return. So we should use netif_napi_add before netif_queue_set_napi because netif_napi_add has "napi->dev =3D dev". Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong Reviewed-by: Vadim Fedorenko --- drivers/net/ethernet/huawei/hinic3/hinic3_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_irq.c index 33eb9080739d..a69b361225e9 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c @@ -42,11 +42,11 @@ static void qp_add_napi(struct hinic3_irq_cfg *irq_cfg) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(irq_cfg->netdev); =20 + netif_napi_add(nic_dev->netdev, &irq_cfg->napi, hinic3_poll); netif_queue_set_napi(irq_cfg->netdev, irq_cfg->irq_id, NETDEV_QUEUE_TYPE_RX, &irq_cfg->napi); netif_queue_set_napi(irq_cfg->netdev, irq_cfg->irq_id, NETDEV_QUEUE_TYPE_TX, &irq_cfg->napi); - netif_napi_add(nic_dev->netdev, &irq_cfg->napi, hinic3_poll); napi_enable(&irq_cfg->napi); } =20 --=20 2.43.0 From nobody Tue Sep 9 21:30:26 2025 Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A6417314A83; Fri, 5 Sep 2025 08:29:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.190 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060971; cv=none; b=PtdZjtcfOoqQ4+wQ2dE9HQuSwQHsxp4AmfHOT7aGP2VNc7Z9a5T2+3Zdoauius/+PH+xi70mCK5Sh4vRlZu/ghU3RQNBhorgtduOmcVoM9XpzdNfQOZFR5nlkQMe3ug39LvzggD4I1nc7pv07D6KMdZ0NqlzGj0XpK/gFC5/KgM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757060971; c=relaxed/simple; bh=s6eDdhRxwiAGwBQu1EeWsS2Kiz3ungjNpeZ+VY7CMBk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CfKwlMYJNxra7XN7pBAI8fvph/res07R6sl4Fvsw4E2J/1Ze5UaONO1KAE1Qy8nkrpxk2tr77EvIOaVeGApQbbVZcDoKbRA/EHeTUrmXb0m609lWONXZrbekMUByR5BIB7jDtAeD8WP6r54bLwBAcoWHevqHGB6lEcN+gvPYbok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.190 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.214]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4cJ8Xn2rCfz2Cg8K; Fri, 5 Sep 2025 16:24:57 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 4B7701A016C; Fri, 5 Sep 2025 16:29:27 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 5 Sep 2025 16:29:25 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v04 14/14] hinic3: Fix code style (Missing a blank line before return) Date: Fri, 5 Sep 2025 16:28:48 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Fix code style of missing a blank line before return. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong Reviewed-by: Vadim Fedorenko --- drivers/net/ethernet/huawei/hinic3/hinic3_lld.c | 5 +++++ drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c | 1 + drivers/net/ethernet/huawei/hinic3/hinic3_tx.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_lld.c index 10477fb9cc34..3db8241a3b0c 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c @@ -122,6 +122,7 @@ static int hinic3_attach_aux_devices(struct hinic3_hwde= v *hwdev) goto err_del_adevs; } mutex_unlock(&pci_adapter->pdev_mutex); + return 0; =20 err_del_adevs: @@ -133,6 +134,7 @@ static int hinic3_attach_aux_devices(struct hinic3_hwde= v *hwdev) } } mutex_unlock(&pci_adapter->pdev_mutex); + return -ENOMEM; } =20 @@ -154,6 +156,7 @@ struct hinic3_hwdev *hinic3_adev_get_hwdev(struct auxil= iary_device *adev) struct hinic3_adev *hadev; =20 hadev =3D container_of(adev, struct hinic3_adev, adev); + return hadev->hwdev; } =20 @@ -335,6 +338,7 @@ static int hinic3_probe_func(struct hinic3_pcidev *pci_= adapter) =20 err_out: dev_err(&pdev->dev, "PCIe device probe function failed\n"); + return err; } =20 @@ -367,6 +371,7 @@ static int hinic3_probe(struct pci_dev *pdev, const str= uct pci_device_id *id) =20 err_out: dev_err(&pdev->dev, "PCIe device probe failed\n"); + return err; } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index 9349b8a314ae..979f47ca77f9 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -112,6 +112,7 @@ int hinic3_set_port_mtu(struct net_device *netdev, u16 = new_mtu) struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; =20 func_tbl_cfg.mtu =3D new_mtu; + return hinic3_set_function_table(hwdev, BIT(L2NIC_FUNC_TBL_CFG_MTU), &func_tbl_cfg); } diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.c index dea882260b11..92c43c05e3f2 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c @@ -116,6 +116,7 @@ static int hinic3_tx_map_skb(struct net_device *netdev,= struct sk_buff *skb, } dma_unmap_single(&pdev->dev, dma_info[0].dma, dma_info[0].len, DMA_TO_DEVICE); + return err; } =20 @@ -601,6 +602,7 @@ netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, stru= ct net_device *netdev) =20 err_drop_pkt: dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } =20 --=20 2.43.0