From nobody Wed Sep 10 02:03:19 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