From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 24A00A04A4; Tue, 28 Dec 2021 03:10:30 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A0C9240040; Tue, 28 Dec 2021 03:10:29 +0100 (CET) Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by mails.dpdk.org (Postfix) with ESMTP id 78CD84003C for ; Tue, 28 Dec 2021 03:10:27 +0100 (CET) Received: from kwepemi100002.china.huawei.com (unknown [172.30.72.57]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4JNHzn3Fsszcc3y; Tue, 28 Dec 2021 10:09:57 +0800 (CST) Received: from kwepemm600004.china.huawei.com (7.193.23.242) by kwepemi100002.china.huawei.com (7.221.188.188) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.20; Tue, 28 Dec 2021 10:10:24 +0800 Received: from [10.67.103.231] (10.67.103.231) by kwepemm600004.china.huawei.com (7.193.23.242) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.20; Tue, 28 Dec 2021 10:10:24 +0800 Message-ID: <9a9afaaf-683a-37ae-251b-42abefb3e1d5@huawei.com> Date: Tue, 28 Dec 2021 10:10:23 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.2.0 Subject: Re: [PATCH v4 02/25] net/spnic: initialize the HW interface To: Yanling Song , CC: , , , References: <3029b106a8d95440f638874f3e8df0f89d61647b.1640426040.git.songyl@ramaxel.com> From: "lihuisong (C)" In-Reply-To: <3029b106a8d95440f638874f3e8df0f89d61647b.1640426040.git.songyl@ramaxel.com> Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 8bit X-Originating-IP: [10.67.103.231] X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemm600004.china.huawei.com (7.193.23.242) X-CFilter-Loop: Reflected X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org 在 2021/12/25 19:28, Yanling Song 写道: > Add HW interface registers and initialize the HW > interface. > > Signed-off-by: Yanling Song > --- > drivers/net/spnic/base/meson.build | 2 + > drivers/net/spnic/base/spnic_csr.h | 104 ++++ > drivers/net/spnic/base/spnic_hwdev.c | 41 ++ > drivers/net/spnic/base/spnic_hwdev.h | 29 + > drivers/net/spnic/base/spnic_hwif.c | 774 +++++++++++++++++++++++++++ > drivers/net/spnic/base/spnic_hwif.h | 155 ++++++ > drivers/net/spnic/spnic_ethdev.c | 66 +++ > drivers/net/spnic/spnic_ethdev.h | 48 +- > 8 files changed, 1212 insertions(+), 7 deletions(-) > create mode 100644 drivers/net/spnic/base/spnic_csr.h > create mode 100644 drivers/net/spnic/base/spnic_hwdev.c > create mode 100644 drivers/net/spnic/base/spnic_hwdev.h > create mode 100644 drivers/net/spnic/base/spnic_hwif.c > create mode 100644 drivers/net/spnic/base/spnic_hwif.h > > diff --git a/drivers/net/spnic/base/meson.build b/drivers/net/spnic/base/meson.build > index e83a473881..edd6e94772 100644 > --- a/drivers/net/spnic/base/meson.build > +++ b/drivers/net/spnic/base/meson.build > @@ -2,6 +2,8 @@ > # Copyright(c) 2021 Ramaxel Memory Technology, Ltd > > sources = [ > + 'spnic_hwdev.c', > + 'spnic_hwif.c' > ] > > extra_flags = [] > diff --git a/drivers/net/spnic/base/spnic_csr.h b/drivers/net/spnic/base/spnic_csr.h > new file mode 100644 > index 0000000000..b4cf7c2593 > --- /dev/null > +++ b/drivers/net/spnic/base/spnic_csr.h > @@ -0,0 +1,104 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Ramaxel Memory Technology, Ltd > + */ > + > +#ifndef _SPNIC_CSR_H_ > +#define _SPNIC_CSR_H_ > + > +#define PCI_VENDOR_ID_RAMAXEL 0x1E81 > + > +/* Device ids */ > +#define SPNIC_DEV_ID_PF 0x9020 > +#define SPNIC_DEV_ID_VF 0x9001 > + > +/* > + * Bit30/bit31 for bar index flag > + * 00: bar0 > + * 01: bar1 > + * 10: bar2 > + * 11: bar3 > + */ > +#define SPNIC_CFG_REGS_FLAG 0x40000000 > + > +#define SPNIC_MGMT_REGS_FLAG 0xC0000000 > + > +#define SPNIC_REGS_FLAG_MASK 0x3FFFFFFF > + > +#define SPNIC_VF_CFG_REG_OFFSET 0x2000 > + > +#define SPNIC_HOST_CSR_BASE_ADDR (SPNIC_MGMT_REGS_FLAG + 0x6000) > +#define SPNIC_CSR_GLOBAL_BASE_ADDR (SPNIC_MGMT_REGS_FLAG + 0x6400) > + > +/* HW interface registers */ > +#define SPNIC_CSR_FUNC_ATTR0_ADDR (SPNIC_CFG_REGS_FLAG + 0x0) > +#define SPNIC_CSR_FUNC_ATTR1_ADDR (SPNIC_CFG_REGS_FLAG + 0x4) > +#define SPNIC_CSR_FUNC_ATTR2_ADDR (SPNIC_CFG_REGS_FLAG + 0x8) > +#define SPNIC_CSR_FUNC_ATTR3_ADDR (SPNIC_CFG_REGS_FLAG + 0xC) > +#define SPNIC_CSR_FUNC_ATTR4_ADDR (SPNIC_CFG_REGS_FLAG + 0x10) > +#define SPNIC_CSR_FUNC_ATTR5_ADDR (SPNIC_CFG_REGS_FLAG + 0x14) > +#define SPNIC_CSR_FUNC_ATTR6_ADDR (SPNIC_CFG_REGS_FLAG + 0x18) > + > +#define SPNIC_FUNC_CSR_MAILBOX_DATA_OFF 0x80 > +#define SPNIC_FUNC_CSR_MAILBOX_CONTROL_OFF (SPNIC_CFG_REGS_FLAG + 0x0100) > +#define SPNIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF (SPNIC_CFG_REGS_FLAG + 0x0104) > +#define SPNIC_FUNC_CSR_MAILBOX_RESULT_H_OFF (SPNIC_CFG_REGS_FLAG + 0x0108) > +#define SPNIC_FUNC_CSR_MAILBOX_RESULT_L_OFF (SPNIC_CFG_REGS_FLAG + 0x010C) > + > +#define SPNIC_PPF_ELECTION_OFFSET 0x0 > +#define SPNIC_MPF_ELECTION_OFFSET 0x20 > + > +#define SPNIC_CSR_PPF_ELECTION_ADDR \ > + (SPNIC_HOST_CSR_BASE_ADDR + SPNIC_PPF_ELECTION_OFFSET) > + > +#define SPNIC_CSR_GLOBAL_MPF_ELECTION_ADDR \ > + (SPNIC_HOST_CSR_BASE_ADDR + SPNIC_MPF_ELECTION_OFFSET) > + > +#define SPNIC_CSR_DMA_ATTR_TBL_ADDR (SPNIC_CFG_REGS_FLAG + 0x380) > +#define SPNIC_CSR_DMA_ATTR_INDIR_IDX_ADDR (SPNIC_CFG_REGS_FLAG + 0x390) > + > +/* MSI-X registers */ > +#define SPNIC_CSR_MSIX_INDIR_IDX_ADDR (SPNIC_CFG_REGS_FLAG + 0x310) > +#define SPNIC_CSR_MSIX_CTRL_ADDR (SPNIC_CFG_REGS_FLAG + 0x300) > +#define SPNIC_CSR_MSIX_CNT_ADDR (SPNIC_CFG_REGS_FLAG + 0x304) > +#define SPNIC_CSR_FUNC_MSI_CLR_WR_ADDR (SPNIC_CFG_REGS_FLAG + 0x58) > + > +#define SPNIC_MSI_CLR_INDIR_RESEND_TIMER_CLR_SHIFT 0 > +#define SPNIC_MSI_CLR_INDIR_INT_MSK_SET_SHIFT 1 > +#define SPNIC_MSI_CLR_INDIR_INT_MSK_CLR_SHIFT 2 > +#define SPNIC_MSI_CLR_INDIR_AUTO_MSK_SET_SHIFT 3 > +#define SPNIC_MSI_CLR_INDIR_AUTO_MSK_CLR_SHIFT 4 > +#define SPNIC_MSI_CLR_INDIR_SIMPLE_INDIR_IDX_SHIFT 22 > + > +#define SPNIC_MSI_CLR_INDIR_RESEND_TIMER_CLR_MASK 0x1U > +#define SPNIC_MSI_CLR_INDIR_INT_MSK_SET_MASK 0x1U > +#define SPNIC_MSI_CLR_INDIR_INT_MSK_CLR_MASK 0x1U > +#define SPNIC_MSI_CLR_INDIR_AUTO_MSK_SET_MASK 0x1U > +#define SPNIC_MSI_CLR_INDIR_AUTO_MSK_CLR_MASK 0x1U > +#define SPNIC_MSI_CLR_INDIR_SIMPLE_INDIR_IDX_MASK 0x3FFU > + > +#define SPNIC_MSI_CLR_INDIR_SET(val, member) \ > + (((val) & SPNIC_MSI_CLR_INDIR_##member##_MASK) << \ > + SPNIC_MSI_CLR_INDIR_##member##_SHIFT) > + > +/* EQ registers */ > +#define SPNIC_AEQ_INDIR_IDX_ADDR (SPNIC_CFG_REGS_FLAG + 0x210) > + > +#define SPNIC_AEQ_MTT_OFF_BASE_ADDR (SPNIC_CFG_REGS_FLAG + 0x240) > + > +#define SPNIC_CSR_EQ_PAGE_OFF_STRIDE 8 > + > +#define SPNIC_AEQ_HI_PHYS_ADDR_REG(pg_num) \ > + (SPNIC_AEQ_MTT_OFF_BASE_ADDR + \ > + (pg_num) * SPNIC_CSR_EQ_PAGE_OFF_STRIDE) > + > +#define SPNIC_AEQ_LO_PHYS_ADDR_REG(pg_num) \ > + (SPNIC_AEQ_MTT_OFF_BASE_ADDR + \ > + (pg_num) * SPNIC_CSR_EQ_PAGE_OFF_STRIDE + 4) > + > +#define SPNIC_CSR_AEQ_CTRL_0_ADDR (SPNIC_CFG_REGS_FLAG + 0x200) > +#define SPNIC_CSR_AEQ_CTRL_1_ADDR (SPNIC_CFG_REGS_FLAG + 0x204) > +#define SPNIC_CSR_AEQ_CONS_IDX_ADDR (SPNIC_CFG_REGS_FLAG + 0x208) > +#define SPNIC_CSR_AEQ_PROD_IDX_ADDR (SPNIC_CFG_REGS_FLAG + 0x20C) > +#define SPNIC_CSR_AEQ_CI_SIMPLE_INDIR_ADDR (SPNIC_CFG_REGS_FLAG + 0x50) > + > +#endif /* _SPNIC_CSR_H_ */ > diff --git a/drivers/net/spnic/base/spnic_hwdev.c b/drivers/net/spnic/base/spnic_hwdev.c > new file mode 100644 > index 0000000000..de73f244fd > --- /dev/null > +++ b/drivers/net/spnic/base/spnic_hwdev.c > @@ -0,0 +1,41 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Ramaxel Memory Technology, Ltd > + */ > + > +#include "spnic_compat.h" > +#include "spnic_csr.h" > +#include "spnic_hwif.h" > +#include "spnic_hwdev.h" > + > +int spnic_init_hwdev(struct spnic_hwdev *hwdev) > +{ > + int err; > + > + hwdev->chip_fault_stats = rte_zmalloc("chip_fault_stats", > + SPNIC_CHIP_FAULT_SIZE, > + RTE_CACHE_LINE_SIZE); > + if (!hwdev->chip_fault_stats) { > + PMD_DRV_LOG(ERR, "Alloc memory for chip_fault_stats failed"); > + return -ENOMEM; > + } > + > + err = spnic_init_hwif(hwdev); > + if (err) { > + PMD_DRV_LOG(ERR, "Initialize hwif failed"); > + goto init_hwif_err; > + } > + > + return 0; > + > +init_hwif_err: > + rte_free(hwdev->chip_fault_stats); > + > + return -EFAULT; > +} > + > +void spnic_free_hwdev(struct spnic_hwdev *hwdev) > +{ > + spnic_free_hwif(hwdev); > + > + rte_free(hwdev->chip_fault_stats); > +} > diff --git a/drivers/net/spnic/base/spnic_hwdev.h b/drivers/net/spnic/base/spnic_hwdev.h > new file mode 100644 > index 0000000000..c89a4fa840 > --- /dev/null > +++ b/drivers/net/spnic/base/spnic_hwdev.h > @@ -0,0 +1,29 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Ramaxel Memory Technology, Ltd > + */ > + > +#ifndef _SPNIC_HWDEV_H_ > +#define _SPNIC_HWDEV_H_ > + > +#include > + > +#define SPNIC_CHIP_FAULT_SIZE (110 * 1024) > + > +struct spnic_hwdev { > + void *dev_handle; /* Pointer to spnic_nic_dev */ > + void *pci_dev; /* Pointer to rte_pci_device */ > + void *eth_dev; /* Pointer to rte_eth_dev */ > + > + uint16_t port_id; > + > + struct spnic_hwif *hwif; > + u8 *chip_fault_stats; > + > + u16 max_vfs; > + u16 link_status; > +}; > + > +int spnic_init_hwdev(struct spnic_hwdev *hwdev); > + > +void spnic_free_hwdev(struct spnic_hwdev *hwdev); > +#endif /* _SPNIC_HWDEV_H_ */ > diff --git a/drivers/net/spnic/base/spnic_hwif.c b/drivers/net/spnic/base/spnic_hwif.c > new file mode 100644 > index 0000000000..d61061ccfa > --- /dev/null > +++ b/drivers/net/spnic/base/spnic_hwif.c > @@ -0,0 +1,774 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Ramaxel Memory Technology, Ltd > + */ > + > +#include > +#include "spnic_compat.h" > +#include "spnic_csr.h" > +#include "spnic_hwdev.h" > +#include "spnic_hwif.h" > + > +#define WAIT_HWIF_READY_TIMEOUT 10000 > + > +#define DB_IDX(db, db_base) \ > + ((u32)(((u64)(db) - (u64)(db_base)) / \ > + SPNIC_DB_PAGE_SIZE)) > + > +#define SPNIC_AF0_FUNC_GLOBAL_IDX_SHIFT 0 > +#define SPNIC_AF0_P2P_IDX_SHIFT 12 > +#define SPNIC_AF0_PCI_INTF_IDX_SHIFT 17 > +#define SPNIC_AF0_VF_IN_PF_SHIFT 20 > +#define SPNIC_AF0_FUNC_TYPE_SHIFT 28 > + > +#define SPNIC_AF0_FUNC_GLOBAL_IDX_MASK 0xFFF > +#define SPNIC_AF0_P2P_IDX_MASK 0x1F > +#define SPNIC_AF0_PCI_INTF_IDX_MASK 0x7 > +#define SPNIC_AF0_VF_IN_PF_MASK 0xFF > +#define SPNIC_AF0_FUNC_TYPE_MASK 0x1 > + > +#define SPNIC_AF0_GET(val, member) \ > + (((val) >> SPNIC_AF0_##member##_SHIFT) & SPNIC_AF0_##member##_MASK) > + > +#define SPNIC_AF1_PPF_IDX_SHIFT 0 > +#define SPNIC_AF1_AEQS_PER_FUNC_SHIFT 8 > +#define SPNIC_AF1_MGMT_INIT_STATUS_SHIFT 30 > +#define SPNIC_AF1_PF_INIT_STATUS_SHIFT 31 > + > +#define SPNIC_AF1_PPF_IDX_MASK 0x3F > +#define SPNIC_AF1_AEQS_PER_FUNC_MASK 0x3 > +#define SPNIC_AF1_MGMT_INIT_STATUS_MASK 0x1 > +#define SPNIC_AF1_PF_INIT_STATUS_MASK 0x1 > + > +#define SPNIC_AF1_GET(val, member) \ > + (((val) >> SPNIC_AF1_##member##_SHIFT) & SPNIC_AF1_##member##_MASK) > + > +#define SPNIC_AF2_CEQS_PER_FUNC_SHIFT 0 > +#define SPNIC_AF2_DMA_ATTR_PER_FUNC_SHIFT 9 > +#define SPNIC_AF2_IRQS_PER_FUNC_SHIFT 16 > + > +#define SPNIC_AF2_CEQS_PER_FUNC_MASK 0x1FF > +#define SPNIC_AF2_DMA_ATTR_PER_FUNC_MASK 0x7 > +#define SPNIC_AF2_IRQS_PER_FUNC_MASK 0x7FF > + > +#define SPNIC_AF2_GET(val, member) \ > + (((val) >> SPNIC_AF2_##member##_SHIFT) & SPNIC_AF2_##member##_MASK) > + > +#define SPNIC_AF3_GLOBAL_VF_ID_OF_NXT_PF_SHIFT 0 > +#define SPNIC_AF3_GLOBAL_VF_ID_OF_PF_SHIFT 16 > + > +#define SPNIC_AF3_GLOBAL_VF_ID_OF_NXT_PF_MASK 0xFFF > +#define SPNIC_AF3_GLOBAL_VF_ID_OF_PF_MASK 0xFFF > + > +#define SPNIC_AF3_GET(val, member) \ > + (((val) >> SPNIC_AF3_##member##_SHIFT) & SPNIC_AF3_##member##_MASK) > + > +#define SPNIC_AF4_DOORBELL_CTRL_SHIFT 0 > +#define SPNIC_AF4_DOORBELL_CTRL_MASK 0x1 > + > +#define SPNIC_AF4_GET(val, member) \ > + (((val) >> SPNIC_AF4_##member##_SHIFT) & SPNIC_AF4_##member##_MASK) > + > +#define SPNIC_AF4_SET(val, member) \ > + (((val) & SPNIC_AF4_##member##_MASK) << SPNIC_AF4_##member##_SHIFT) > + > +#define SPNIC_AF4_CLEAR(val, member) \ > + ((val) & (~(SPNIC_AF4_##member##_MASK << \ > + SPNIC_AF4_##member##_SHIFT))) > + > +#define SPNIC_AF5_OUTBOUND_CTRL_SHIFT 0 > +#define SPNIC_AF5_OUTBOUND_CTRL_MASK 0x1 > + > +#define SPNIC_AF5_GET(val, member) \ > + (((val) >> SPNIC_AF5_##member##_SHIFT) & SPNIC_AF5_##member##_MASK) > + > +#define SPNIC_AF5_SET(val, member) \ > + (((val) & SPNIC_AF5_##member##_MASK) << SPNIC_AF5_##member##_SHIFT) > + > +#define SPNIC_AF5_CLEAR(val, member) \ > + ((val) & (~(SPNIC_AF5_##member##_MASK << \ > + SPNIC_AF5_##member##_SHIFT))) > + > +#define SPNIC_AF6_PF_STATUS_SHIFT 0 > +#define SPNIC_AF6_PF_STATUS_MASK 0xFFFF > + > +#define SPNIC_AF6_SET(val, member) \ > + ((((u32)(val)) & SPNIC_AF6_##member##_MASK) << \ > + SPNIC_AF6_##member##_SHIFT) > + > +#define SPNIC_AF6_GET(val, member) \ > + (((val) >> SPNIC_AF6_##member##_SHIFT) & SPNIC_AF6_##member##_MASK) > + > +#define SPNIC_AF6_CLEAR(val, member) \ > + ((val) & (~(SPNIC_AF6_##member##_MASK << \ > + SPNIC_AF6_##member##_SHIFT))) > + > +#define SPNIC_PPF_ELECTION_IDX_SHIFT 0 > + > +#define SPNIC_PPF_ELECTION_IDX_MASK 0x3F > + > +#define SPNIC_PPF_ELECTION_SET(val, member) \ > + (((val) & SPNIC_PPF_ELECTION_##member##_MASK) << \ > + SPNIC_PPF_ELECTION_##member##_SHIFT) > + > +#define SPNIC_PPF_ELECTION_GET(val, member) \ > + (((val) >> SPNIC_PPF_ELECTION_##member##_SHIFT) & \ > + SPNIC_PPF_ELECTION_##member##_MASK) > + > +#define SPNIC_PPF_ELECTION_CLEAR(val, member) \ > + ((val) & (~(SPNIC_PPF_ELECTION_##member##_MASK \ > + << SPNIC_PPF_ELECTION_##member##_SHIFT))) > + > +#define SPNIC_MPF_ELECTION_IDX_SHIFT 0 > + > +#define SPNIC_MPF_ELECTION_IDX_MASK 0x1F > + > +#define SPNIC_MPF_ELECTION_SET(val, member) \ > + (((val) & SPNIC_MPF_ELECTION_##member##_MASK) << \ > + SPNIC_MPF_ELECTION_##member##_SHIFT) > + > +#define SPNIC_MPF_ELECTION_GET(val, member) \ > + (((val) >> SPNIC_MPF_ELECTION_##member##_SHIFT) & \ > + SPNIC_MPF_ELECTION_##member##_MASK) > + > +#define SPNIC_MPF_ELECTION_CLEAR(val, member) \ > + ((val) & (~(SPNIC_MPF_ELECTION_##member##_MASK \ > + << SPNIC_MPF_ELECTION_##member##_SHIFT))) > + > +#define SPNIC_GET_REG_FLAG(reg) ((reg) & (~(SPNIC_REGS_FLAG_MASK))) > + > +#define SPNIC_GET_REG_ADDR(reg) ((reg) & (SPNIC_REGS_FLAG_MASK)) > + > +#define SPNIC_IS_VF_DEV(pdev) ((pdev)->id.device_id == SPNIC_DEV_ID_VF) > + > +u32 spnic_hwif_read_reg(struct spnic_hwif *hwif, u32 reg) > +{ > + if (SPNIC_GET_REG_FLAG(reg) == SPNIC_MGMT_REGS_FLAG) > + return be32_to_cpu(rte_read32(hwif->mgmt_regs_base + > + SPNIC_GET_REG_ADDR(reg))); > + else > + return be32_to_cpu(rte_read32(hwif->cfg_regs_base + > + SPNIC_GET_REG_ADDR(reg))); > +} > + > +void spnic_hwif_write_reg(struct spnic_hwif *hwif, u32 reg, u32 val) > +{ > + if (SPNIC_GET_REG_FLAG(reg) == SPNIC_MGMT_REGS_FLAG) > + rte_write32(cpu_to_be32(val), > + hwif->mgmt_regs_base + SPNIC_GET_REG_ADDR(reg)); > + else > + rte_write32(cpu_to_be32(val), > + hwif->cfg_regs_base + SPNIC_GET_REG_ADDR(reg)); > +} > + > +/** > + * Judge whether HW initialization ok > + * > + * @param[in] hwdev > + * The pointer to the private hardware device object > + * > + * @retval zero: Success > + * @retval negative: Failure > + */ > +static int hwif_ready(struct spnic_hwdev *hwdev) > +{ > + u32 addr, attr1; > + > + addr = SPNIC_CSR_FUNC_ATTR1_ADDR; > + attr1 = spnic_hwif_read_reg(hwdev->hwif, addr); > + if (attr1 == SPNIC_PCIE_LINK_DOWN) > + return -EBUSY; > + > + if (!SPNIC_AF1_GET(attr1, MGMT_INIT_STATUS)) > + return -EBUSY; > + > + return 0; > +} > + > +static int wait_hwif_ready(struct spnic_hwdev *hwdev) > +{ > + u64 timeout = 0; > + > + do { > + if (!hwif_ready(hwdev)) > + return 0; > + > + rte_delay_ms(1); > + timeout++; > + } while (timeout <= WAIT_HWIF_READY_TIMEOUT); > + > + PMD_DRV_LOG(ERR, "Hwif is not ready"); > + return -EBUSY; > +} > + > +/** > + * Set the attributes as members in hwif > + * > + * @param[in] hwif > + * The hardware interface of a pci function device > + * @param[in] attr0 > + * The first attribute that was read from the hw > + * @param[in] attr1 > + * The second attribute that was read from the hw > + * @param[in] attr2 > + * The third attribute that was read from the hw > + * @param[in] attr3 > + * The fourth attribute that was read from the hw > + */ > +static void set_hwif_attr(struct spnic_hwif *hwif, u32 attr0, u32 attr1, > + u32 attr2, u32 attr3) > +{ > + hwif->attr.func_global_idx = SPNIC_AF0_GET(attr0, FUNC_GLOBAL_IDX); > + hwif->attr.port_to_port_idx = SPNIC_AF0_GET(attr0, P2P_IDX); > + hwif->attr.pci_intf_idx = SPNIC_AF0_GET(attr0, PCI_INTF_IDX); > + hwif->attr.vf_in_pf = SPNIC_AF0_GET(attr0, VF_IN_PF); > + hwif->attr.func_type = SPNIC_AF0_GET(attr0, FUNC_TYPE); > + > + hwif->attr.ppf_idx = SPNIC_AF1_GET(attr1, PPF_IDX); > + hwif->attr.num_aeqs = BIT(SPNIC_AF1_GET(attr1, AEQS_PER_FUNC)); > + > + hwif->attr.num_ceqs = (u8)SPNIC_AF2_GET(attr2, CEQS_PER_FUNC); > + hwif->attr.num_irqs = SPNIC_AF2_GET(attr2, IRQS_PER_FUNC); > + hwif->attr.num_dma_attr = BIT(SPNIC_AF2_GET(attr2, DMA_ATTR_PER_FUNC)); > + > + hwif->attr.global_vf_id_of_pf = SPNIC_AF3_GET(attr3, > + GLOBAL_VF_ID_OF_PF); > +} > + > +/** > + * Read and set the attributes as members in hwif > + * > + * @param[in] hwif > + * The hardware interface of a pci function device > + */ > +static void get_hwif_attr(struct spnic_hwif *hwif) > +{ > + u32 addr, attr0, attr1, attr2, attr3; > + > + addr = SPNIC_CSR_FUNC_ATTR0_ADDR; > + attr0 = spnic_hwif_read_reg(hwif, addr); > + > + addr = SPNIC_CSR_FUNC_ATTR1_ADDR; > + attr1 = spnic_hwif_read_reg(hwif, addr); > + > + addr = SPNIC_CSR_FUNC_ATTR2_ADDR; > + attr2 = spnic_hwif_read_reg(hwif, addr); > + > + addr = SPNIC_CSR_FUNC_ATTR3_ADDR; > + attr3 = spnic_hwif_read_reg(hwif, addr); > + > + set_hwif_attr(hwif, attr0, attr1, attr2, attr3); > +} > + > +void spnic_set_pf_status(struct spnic_hwif *hwif, enum spnic_pf_status status) > +{ > + u32 attr6 = SPNIC_AF6_SET(status, PF_STATUS); > + u32 addr = SPNIC_CSR_FUNC_ATTR6_ADDR; > + > + if (hwif->attr.func_type == TYPE_VF) > + return; > + > + spnic_hwif_write_reg(hwif, addr, attr6); > +} > + > +enum spnic_pf_status spnic_get_pf_status(struct spnic_hwif *hwif) > +{ > + u32 attr6 = spnic_hwif_read_reg(hwif, SPNIC_CSR_FUNC_ATTR6_ADDR); > + > + return SPNIC_AF6_GET(attr6, PF_STATUS); > +} > + > +static enum spnic_doorbell_ctrl > +spnic_get_doorbell_ctrl_status(struct spnic_hwif *hwif) > +{ > + u32 attr4 = spnic_hwif_read_reg(hwif, SPNIC_CSR_FUNC_ATTR4_ADDR); > + > + return SPNIC_AF4_GET(attr4, DOORBELL_CTRL); > +} > + > +static enum spnic_outbound_ctrl > +spnic_get_outbound_ctrl_status(struct spnic_hwif *hwif) > +{ > + u32 attr5 = spnic_hwif_read_reg(hwif, SPNIC_CSR_FUNC_ATTR5_ADDR); > + > + return SPNIC_AF5_GET(attr5, OUTBOUND_CTRL); > +} > + > +void spnic_enable_doorbell(struct spnic_hwif *hwif) > +{ > + u32 addr, attr4; > + > + addr = SPNIC_CSR_FUNC_ATTR4_ADDR; > + attr4 = spnic_hwif_read_reg(hwif, addr); > + > + attr4 = SPNIC_AF4_CLEAR(attr4, DOORBELL_CTRL); > + attr4 |= SPNIC_AF4_SET(ENABLE_DOORBELL, DOORBELL_CTRL); > + > + spnic_hwif_write_reg(hwif, addr, attr4); > +} > + > +void spnic_disable_doorbell(struct spnic_hwif *hwif) > +{ > + u32 addr, attr4; > + > + addr = SPNIC_CSR_FUNC_ATTR4_ADDR; > + attr4 = spnic_hwif_read_reg(hwif, addr); > + > + attr4 = SPNIC_AF4_CLEAR(attr4, DOORBELL_CTRL); > + attr4 |= SPNIC_AF4_SET(DISABLE_DOORBELL, DOORBELL_CTRL); > + > + spnic_hwif_write_reg(hwif, addr, attr4); > +} > + > +/** > + * Try to set hwif as ppf and set the type of hwif in this case > + * > + * @param[in] hwif > + * The hardware interface of a pci function device > + */ > +static void set_ppf(struct spnic_hwif *hwif) > +{ > + struct spnic_func_attr *attr = &hwif->attr; > + u32 addr, val, ppf_election; > + > + addr = SPNIC_CSR_PPF_ELECTION_ADDR; > + > + val = spnic_hwif_read_reg(hwif, addr); > + val = SPNIC_PPF_ELECTION_CLEAR(val, IDX); > + > + ppf_election = SPNIC_PPF_ELECTION_SET(attr->func_global_idx, IDX); > + val |= ppf_election; > + > + spnic_hwif_write_reg(hwif, addr, val); > + > + /* Check PPF */ > + val = spnic_hwif_read_reg(hwif, addr); > + > + attr->ppf_idx = SPNIC_PPF_ELECTION_GET(val, IDX); > + if (attr->ppf_idx == attr->func_global_idx) > + attr->func_type = TYPE_PPF; > +} > + > +/** > + * Get the mpf index from the hwif > + * > + * @param[in] hwif > + * The hardware interface of a pci function device > + */ > +static void get_mpf(struct spnic_hwif *hwif) > +{ > + struct spnic_func_attr *attr = &hwif->attr; > + u32 mpf_election, addr; > + > + addr = SPNIC_CSR_GLOBAL_MPF_ELECTION_ADDR; > + > + mpf_election = spnic_hwif_read_reg(hwif, addr); > + attr->mpf_idx = SPNIC_MPF_ELECTION_GET(mpf_election, IDX); > +} > + > +/** > + * Try to set hwif as mpf and set the mpf idx in hwif > + * > + * @param[in] hwif > + * The hardware interface of a pci function device > + */ > +static void set_mpf(struct spnic_hwif *hwif) > +{ > + struct spnic_func_attr *attr = &hwif->attr; > + u32 addr, val, mpf_election; > + > + addr = SPNIC_CSR_GLOBAL_MPF_ELECTION_ADDR; > + > + val = spnic_hwif_read_reg(hwif, addr); > + > + val = SPNIC_MPF_ELECTION_CLEAR(val, IDX); > + mpf_election = SPNIC_MPF_ELECTION_SET(attr->func_global_idx, IDX); > + > + val |= mpf_election; > + spnic_hwif_write_reg(hwif, addr, val); > +} > + > +static void init_db_area_idx(struct spnic_free_db_area *free_db_area, > + u64 db_dwqe_len) > +{ > + u32 i, db_max_areas; > + > + db_max_areas = (db_dwqe_len > SPNIC_DB_DWQE_SIZE) ? > + SPNIC_DB_MAX_AREAS : > + (u32)(db_dwqe_len / SPNIC_DB_PAGE_SIZE); > + > + for (i = 0; i < db_max_areas; i++) > + free_db_area->db_idx[i] = i; > + > + free_db_area->num_free = db_max_areas; > + free_db_area->db_max_areas = db_max_areas; > + > + rte_spinlock_init(&free_db_area->idx_lock); > +} > + > +static int get_db_idx(struct spnic_hwif *hwif, u32 *idx) > +{ > + struct spnic_free_db_area *free_db_area = &hwif->free_db_area; > + u32 pos; > + u32 pg_idx; > + > + rte_spinlock_lock(&free_db_area->idx_lock); > + > + do { > + if (free_db_area->num_free == 0) { > + rte_spinlock_unlock(&free_db_area->idx_lock); > + return -ENOMEM; > + } > + > + free_db_area->num_free--; > + > + pos = free_db_area->alloc_pos++; > + /* Doorbell max areas should be 2^n */ > + pos &= free_db_area->db_max_areas - 1; > + > + pg_idx = free_db_area->db_idx[pos]; > + > + free_db_area->db_idx[pos] = 0xFFFFFFFF; > + } while (pg_idx >= free_db_area->db_max_areas); > + > + rte_spinlock_unlock(&free_db_area->idx_lock); > + > + *idx = pg_idx; > + > + return 0; > +} > + > +static void free_db_idx(struct spnic_hwif *hwif, u32 idx) > +{ > + struct spnic_free_db_area *free_db_area = &hwif->free_db_area; > + u32 pos; > + > + if (idx >= free_db_area->db_max_areas) > + return; > + > + rte_spinlock_lock(&free_db_area->idx_lock); > + > + pos = free_db_area->return_pos++; > + pos &= free_db_area->db_max_areas - 1; > + > + free_db_area->db_idx[pos] = idx; > + > + free_db_area->num_free++; > + > + rte_spinlock_unlock(&free_db_area->idx_lock); > +} > + > +void spnic_free_db_addr(void *hwdev, const void *db_base, > + __rte_unused void *dwqe_base) > +{ > + struct spnic_hwif *hwif = NULL; > + u32 idx; > + > + if (!hwdev || !db_base) > + return; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + idx = DB_IDX(db_base, hwif->db_base); > + > + free_db_idx(hwif, idx); > +} > + > +int spnic_alloc_db_addr(void *hwdev, void **db_base, void **dwqe_base) > +{ > + struct spnic_hwif *hwif = NULL; > + u32 idx; > + int err; > + > + if (!hwdev || !db_base) > + return -EINVAL; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + > + err = get_db_idx(hwif, &idx); > + if (err) > + return -EFAULT; > + > + *db_base = hwif->db_base + idx * SPNIC_DB_PAGE_SIZE; > + > + if (!dwqe_base) > + return 0; > + > + *dwqe_base = (u8 *)*db_base + SPNIC_DWQE_OFFSET; > + > + return 0; > +} > + > +/** > + * Set msix state > + * > + * @param[in] hwdev > + * The pointer to the private hardware device object > + * @param[in] msix_idx > + * MSIX index > + * @param[in] flag > + * MSIX state flag, 0-enable, 1-disable > + */ > +void spnic_set_msix_state(void *hwdev, u16 msix_idx, enum spnic_msix_state flag) > +{ > + struct spnic_hwif *hwif = NULL; > + u32 mask_bits; > + u32 addr; > + u8 int_msk = 1; > + > + if (!hwdev) > + return; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + > + if (flag) > + mask_bits = SPNIC_MSI_CLR_INDIR_SET(int_msk, INT_MSK_SET); > + else > + mask_bits = SPNIC_MSI_CLR_INDIR_SET(int_msk, INT_MSK_CLR); > + mask_bits = mask_bits | > + SPNIC_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX); > + > + addr = SPNIC_CSR_FUNC_MSI_CLR_WR_ADDR; > + spnic_hwif_write_reg(hwif, addr, mask_bits); > +} > + > +static void disable_all_msix(struct spnic_hwdev *hwdev) > +{ > + u16 num_irqs = hwdev->hwif->attr.num_irqs; > + u16 i; > + > + for (i = 0; i < num_irqs; i++) > + spnic_set_msix_state(hwdev, i, SPNIC_MSIX_DISABLE); > +} > + > +void spnic_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx, > + u8 clear_resend_en) > +{ > + struct spnic_hwif *hwif = NULL; > + u32 msix_ctrl = 0, addr; > + > + if (!hwdev) > + return; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + > + msix_ctrl = SPNIC_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX) | > + SPNIC_MSI_CLR_INDIR_SET(clear_resend_en, RESEND_TIMER_CLR); > + > + addr = SPNIC_CSR_FUNC_MSI_CLR_WR_ADDR; > + spnic_hwif_write_reg(hwif, addr, msix_ctrl); > +} > +#ifdef SPNIC_RELEASE > +static int wait_until_doorbell_flush_states(struct spnic_hwif *hwif, > + enum spnic_doorbell_ctrl states) > +{ > + enum spnic_doorbell_ctrl db_ctrl; > + u32 cnt = 0; > + > + if (!hwif) > + return -EINVAL; > + > + while (cnt < SPNIC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT) { > + db_ctrl = spnic_get_doorbell_ctrl_status(hwif); > + if (db_ctrl == states) > + return 0; > + > + rte_delay_ms(1); > + cnt++; > + } > + > + return -EFAULT; > +} > +#endif > + > +static int wait_until_doorbell_and_outbound_enabled(struct spnic_hwif *hwif) > +{ > + enum spnic_doorbell_ctrl db_ctrl; > + enum spnic_outbound_ctrl outbound_ctrl; > + u32 cnt = 0; > + > + while (cnt < SPNIC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT) { > + db_ctrl = spnic_get_doorbell_ctrl_status(hwif); > + outbound_ctrl = spnic_get_outbound_ctrl_status(hwif); > + if (outbound_ctrl == ENABLE_OUTBOUND && > + db_ctrl == ENABLE_DOORBELL) > + return 0; > + > + rte_delay_ms(1); > + cnt++; > + } > + > + return -EFAULT; > +} > + > +static void spnic_get_bar_addr(struct spnic_hwdev *hwdev) > +{ > + struct rte_pci_device *pci_dev = hwdev->pci_dev; > + struct spnic_hwif *hwif = hwdev->hwif; > + void *cfg_regs_base = NULL; > + void *mgmt_reg_base = NULL; > + void *intr_reg_base = NULL; > + void *db_base = NULL; > + int cfg_bar; > + > + cfg_bar = SPNIC_IS_VF_DEV(pci_dev) ? > + SPNIC_VF_PCI_CFG_REG_BAR : SPNIC_PF_PCI_CFG_REG_BAR; > + > + cfg_regs_base = pci_dev->mem_resource[cfg_bar].addr; > + intr_reg_base = pci_dev->mem_resource[SPNIC_PCI_INTR_REG_BAR].addr; > + if (!SPNIC_IS_VF_DEV(pci_dev)) { > + mgmt_reg_base = > + pci_dev->mem_resource[SPNIC_PCI_MGMT_REG_BAR].addr; > + } > + db_base = pci_dev->mem_resource[SPNIC_PCI_DB_BAR].addr; > + > + /* If function is VF, mgmt_regs_base will be NULL */ > + if (!mgmt_reg_base) > + hwif->cfg_regs_base = (u8 *)cfg_regs_base + > + SPNIC_VF_CFG_REG_OFFSET; > + else > + hwif->cfg_regs_base = cfg_regs_base; > + hwif->intr_regs_base = intr_reg_base; > + hwif->mgmt_regs_base = mgmt_reg_base; > + hwif->db_base = db_base; > + hwif->db_dwqe_len = pci_dev->mem_resource[SPNIC_PCI_DB_BAR].len; > +} > + > +/** > + * Initialize the hw interface > + * > + * @param[in] hwdev > + * The pointer to the private hardware device object > + * > + * @retval zero : Success > + * @retval non-zero : Failure. > + */ > +int spnic_init_hwif(void *dev) > +{ > + struct spnic_hwdev *hwdev = NULL; > + struct spnic_hwif *hwif; > + int err; > + > + hwif = rte_zmalloc("spnic_hwif", sizeof(struct spnic_hwif), > + RTE_CACHE_LINE_SIZE); > + if (!hwif) > + return -ENOMEM; > + > + hwdev = (struct spnic_hwdev *)dev; > + hwdev->hwif = hwif; > + > + spnic_get_bar_addr(hwdev); > + > + init_db_area_idx(&hwif->free_db_area, hwif->db_dwqe_len); > + > + err = wait_hwif_ready(hwdev); > + if (err) { > + PMD_DRV_LOG(ERR, "Chip status is not ready"); > + goto hwif_ready_err; > + } > + > + get_hwif_attr(hwif); > + > + err = wait_until_doorbell_and_outbound_enabled(hwif); > + if (err) { > + PMD_DRV_LOG(ERR, "Hw doorbell/outbound is disabled"); > + goto hwif_ready_err; > + } > + > + if (!SPNIC_IS_VF(hwdev)) { > + set_ppf(hwif); > + > + if (SPNIC_IS_PPF(hwdev)) > + set_mpf(hwif); > + > + get_mpf(hwif); > + } > + > + disable_all_msix(hwdev); > + /* Disable mgmt cpu reporting any event */ > + spnic_set_pf_status(hwdev->hwif, SPNIC_PF_STATUS_INIT); > + > + PMD_DRV_LOG(INFO, "global_func_idx: %d, func_type: %d, host_id: %d, ppf: %d, mpf: %d", > + hwif->attr.func_global_idx, hwif->attr.func_type, > + hwif->attr.pci_intf_idx, hwif->attr.ppf_idx, > + hwif->attr.mpf_idx); > + > + return 0; > + > +hwif_ready_err: > + rte_free(hwdev->hwif); > + hwdev->hwif = NULL; > + > + return err; > +} > + > +/** > + * Free the hw interface > + * > + * @param[in] dev > + * The pointer to the private hardware device object > + */ > +void spnic_free_hwif(void *dev) > +{ > + struct spnic_hwdev *hwdev = (struct spnic_hwdev *)dev; > + > + rte_free(hwdev->hwif); > +} > + > +u16 spnic_global_func_id(void *hwdev) > +{ > + struct spnic_hwif *hwif = NULL; > + > + if (!hwdev) > + return 0; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + > + return hwif->attr.func_global_idx; > +} > + > +u8 spnic_pf_id_of_vf(void *hwdev) > +{ > + struct spnic_hwif *hwif = NULL; > + > + if (!hwdev) > + return 0; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + > + return hwif->attr.port_to_port_idx; > +} > + > +u8 spnic_pcie_itf_id(void *hwdev) > +{ > + struct spnic_hwif *hwif = NULL; > + > + if (!hwdev) > + return 0; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + > + return hwif->attr.pci_intf_idx; > +} > + > +enum func_type spnic_func_type(void *hwdev) > +{ > + struct spnic_hwif *hwif = NULL; > + > + if (!hwdev) > + return 0; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + > + return hwif->attr.func_type; > +} > + > +u16 spnic_glb_pf_vf_offset(void *hwdev) > +{ > + struct spnic_hwif *hwif = NULL; > + > + if (!hwdev) > + return 0; > + > + hwif = ((struct spnic_hwdev *)hwdev)->hwif; > + > + return hwif->attr.global_vf_id_of_pf; > +} > diff --git a/drivers/net/spnic/base/spnic_hwif.h b/drivers/net/spnic/base/spnic_hwif.h > new file mode 100644 > index 0000000000..e2be026cba > --- /dev/null > +++ b/drivers/net/spnic/base/spnic_hwif.h > @@ -0,0 +1,155 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2021 Ramaxel Memory Technology, Ltd > + */ > + > +#ifndef _SPNIC_HWIF_H_ > +#define _SPNIC_HWIF_H_ > + > +#define SPNIC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT 60000 > +#define SPNIC_PCIE_LINK_DOWN 0xFFFFFFFF > + > +/* PCIe bar space */ > +#define SPNIC_VF_PCI_CFG_REG_BAR 0 > +#define SPNIC_PF_PCI_CFG_REG_BAR 1 > + > +#define SPNIC_PCI_INTR_REG_BAR 2 > +#define SPNIC_PCI_MGMT_REG_BAR 3 /* Only PF has mgmt bar */ > +#define SPNIC_PCI_DB_BAR 4 > + > +#define SPNIC_DB_DWQE_SIZE 0x00400000 > + > +/* Doorbell or direct wqe page size is 4K */ > +#define SPNIC_DB_PAGE_SIZE 0x00001000ULL > +#define SPNIC_DWQE_OFFSET 0x00000800ULL > + > +#define SPNIC_DB_MAX_AREAS (SPNIC_DB_DWQE_SIZE / SPNIC_DB_PAGE_SIZE) > + > +enum func_type { > + TYPE_PF, > + TYPE_VF, > + TYPE_PPF, > + TYPE_UNKNOWN > +}; > + > +enum spnic_msix_state { > + SPNIC_MSIX_ENABLE, > + SPNIC_MSIX_DISABLE > +}; > + > +struct spnic_free_db_area { > + u32 db_idx[SPNIC_DB_MAX_AREAS]; > + > + u32 num_free; > + > + u32 alloc_pos; > + u32 return_pos; > + u32 db_max_areas; > + > + /* Spinlock for allocating doorbell area */ > + rte_spinlock_t idx_lock; > +}; > + > +struct spnic_func_attr { > + u16 func_global_idx; > + u8 port_to_port_idx; > + u8 pci_intf_idx; > + u8 vf_in_pf; > + enum func_type func_type; > + > + u8 mpf_idx; > + > + u8 ppf_idx; > + > + u16 num_irqs; /* Max: 2 ^ 15 */ > + u8 num_aeqs; /* Max: 2 ^ 3 */ > + u8 num_ceqs; /* Max: 2 ^ 7 */ > + > + u8 num_dma_attr; /* Max: 2 ^ 6 */ > + > + u16 global_vf_id_of_pf; > +}; > + > +struct spnic_hwif { > + /* Configure virtual address, PF is bar1, VF is bar0/1 */ > + u8 *cfg_regs_base; > + /* Interrupt configuration register address, PF is bar2, VF is bar2/3 */ > + u8 *intr_regs_base; > + /* For PF bar3 virtual address, if function is VF should set NULL */ > + u8 *mgmt_regs_base; > + u8 *db_base; > + u64 db_dwqe_len; > + struct spnic_free_db_area free_db_area; > + > + struct spnic_func_attr attr; > + > + void *pdev; > +}; > + > +enum spnic_outbound_ctrl { > + ENABLE_OUTBOUND = 0x0, > + DISABLE_OUTBOUND = 0x1 > +}; > + > +enum spnic_doorbell_ctrl { > + ENABLE_DOORBELL = 0x0, > + DISABLE_DOORBELL = 0x1 > +}; > + > +enum spnic_pf_status { > + SPNIC_PF_STATUS_INIT = 0X0, > + SPNIC_PF_STATUS_ACTIVE_FLAG = 0x11, > + SPNIC_PF_STATUS_FLR_START_FLAG = 0x12, > + SPNIC_PF_STATUS_FLR_FINISH_FLAG = 0x13 > +}; > + > +#define SPNIC_HWIF_NUM_AEQS(hwif) ((hwif)->attr.num_aeqs) > +#define SPNIC_HWIF_NUM_IRQS(hwif) ((hwif)->attr.num_irqs) > +#define SPNIC_HWIF_GLOBAL_IDX(hwif) ((hwif)->attr.func_global_idx) > +#define SPNIC_HWIF_GLOBAL_VF_OFFSET(hwif) ((hwif)->attr.global_vf_id_of_pf) > +#define SPNIC_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx) > +#define SPNIC_PCI_INTF_IDX(hwif) ((hwif)->attr.pci_intf_idx) > + > +#define SPNIC_FUNC_TYPE(dev) ((dev)->hwif->attr.func_type) > +#define SPNIC_IS_PF(dev) (SPNIC_FUNC_TYPE(dev) == TYPE_PF) > +#define SPNIC_IS_VF(dev) (SPNIC_FUNC_TYPE(dev) == TYPE_VF) > +#define SPNIC_IS_PPF(dev) (SPNIC_FUNC_TYPE(dev) == TYPE_PPF) > + > +u32 spnic_hwif_read_reg(struct spnic_hwif *hwif, u32 reg); > + > +void spnic_hwif_write_reg(struct spnic_hwif *hwif, u32 reg, u32 val); > + > +void spnic_set_msix_state(void *hwdev, u16 msix_idx, > + enum spnic_msix_state flag); > + > +void spnic_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx, > + u8 clear_resend_en); > + > +u16 spnic_global_func_id(void *hwdev); > + > +u8 spnic_pf_id_of_vf(void *hwdev); > + > +u8 spnic_pcie_itf_id(void *hwdev); > + > +enum func_type spnic_func_type(void *hwdev); > + > +u16 spnic_glb_pf_vf_offset(void *hwdev); > + > +void spnic_set_pf_status(struct spnic_hwif *hwif, > + enum spnic_pf_status status); > + > +enum spnic_pf_status spnic_get_pf_status(struct spnic_hwif *hwif); > + > +int spnic_alloc_db_addr(void *hwdev, void **db_base, void **dwqe_base); > + > +void spnic_free_db_addr(void *hwdev, const void *db_base, > + __rte_unused void *dwqe_base); > + > +void spnic_disable_doorbell(struct spnic_hwif *hwif); > + > +void spnic_enable_doorbell(struct spnic_hwif *hwif); > + > +int spnic_init_hwif(void *dev); > + > +void spnic_free_hwif(void *dev); > + > +#endif /* _SPNIC_HWIF_H_ */ > diff --git a/drivers/net/spnic/spnic_ethdev.c b/drivers/net/spnic/spnic_ethdev.c > index b06492a8e9..228ed0c936 100644 > --- a/drivers/net/spnic/spnic_ethdev.c > +++ b/drivers/net/spnic/spnic_ethdev.c > @@ -9,15 +9,48 @@ > #include > > #include "base/spnic_compat.h" > +#include "base/spnic_csr.h" > +#include "base/spnic_hwdev.h" > +#include "base/spnic_hwif.h" > + > #include "spnic_ethdev.h" > > /* Driver-specific log messages type */ > int spnic_logtype; > > +#define SPNIC_MAX_UC_MAC_ADDRS 128 > +#define SPNIC_MAX_MC_MAC_ADDRS 128 > + > +/** > + * Close the device. > + * > + * @param[in] dev > + * Pointer to ethernet device structure. > + */ > +static int spnic_dev_close(struct rte_eth_dev *eth_dev) > +{ > + struct spnic_nic_dev *nic_dev = > + SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev); > + > + if (rte_bit_relaxed_test_and_set32(SPNIC_DEV_CLOSE, &nic_dev->dev_status)) { > + PMD_DRV_LOG(WARNING, "Device %s already closed", > + nic_dev->dev_name); > + return 0; > + } > + > + spnic_free_hwdev(nic_dev->hwdev); > + > + rte_free(nic_dev->hwdev); > + nic_dev->hwdev = NULL; > + > + return 0; > +} > + > static int spnic_func_init(struct rte_eth_dev *eth_dev) > { > struct spnic_nic_dev *nic_dev = NULL; > struct rte_pci_device *pci_dev = NULL; > + int err; > > pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); > > @@ -35,11 +68,42 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev) > pci_dev->addr.domain, pci_dev->addr.bus, > pci_dev->addr.devid, pci_dev->addr.function); > > + eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS; Please do not use the temporary macro. Please review this patch: f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats") > + /* Create hardware device */ > + nic_dev->hwdev = rte_zmalloc("spnic_hwdev", sizeof(*nic_dev->hwdev), > + RTE_CACHE_LINE_SIZE); > + if (!nic_dev->hwdev) { > + PMD_DRV_LOG(ERR, "Allocate hwdev memory failed, dev_name: %s", > + eth_dev->data->name); > + err = -ENOMEM; > + goto alloc_hwdev_mem_fail; > + } > + nic_dev->hwdev->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); > + nic_dev->hwdev->dev_handle = nic_dev; > + nic_dev->hwdev->eth_dev = eth_dev; > + nic_dev->hwdev->port_id = eth_dev->data->port_id; > + > + err = spnic_init_hwdev(nic_dev->hwdev); > + if (err) { > + PMD_DRV_LOG(ERR, "Init chip hwdev failed, dev_name: %s", > + eth_dev->data->name); > + goto init_hwdev_fail; > + } > + > rte_bit_relaxed_set32(SPNIC_DEV_INIT, &nic_dev->dev_status); > PMD_DRV_LOG(INFO, "Initialize %s in primary succeed", > eth_dev->data->name); > > return 0; > + > +init_hwdev_fail: > + rte_free(nic_dev->hwdev); > + nic_dev->hwdev = NULL; > + > +alloc_hwdev_mem_fail: > + PMD_DRV_LOG(ERR, "Initialize %s in primary failed", > + eth_dev->data->name); > + return err; > } > > static int spnic_dev_init(struct rte_eth_dev *eth_dev) > @@ -67,6 +131,8 @@ static int spnic_dev_uninit(struct rte_eth_dev *dev) > if (rte_eal_process_type() != RTE_PROC_PRIMARY) > return 0; > > + spnic_dev_close(dev); > + > return 0; > } > > diff --git a/drivers/net/spnic/spnic_ethdev.h b/drivers/net/spnic/spnic_ethdev.h > index d4ec641d83..654234aaa4 100644 > --- a/drivers/net/spnic/spnic_ethdev.h > +++ b/drivers/net/spnic/spnic_ethdev.h > @@ -5,21 +5,55 @@ > #ifndef _SPNIC_ETHDEV_H_ > #define _SPNIC_ETHDEV_H_ > > -/* Vendor id */ > -#define PCI_VENDOR_ID_RAMAXEL 0x1E81 > - > -/* Device ids */ > -#define SPNIC_DEV_ID_PF 0x9020 > -#define SPNIC_DEV_ID_VF 0x9001 > +#define SPNIC_UINT32_BIT_SIZE (CHAR_BIT * sizeof(uint32_t)) > +#define SPNIC_VFTA_SIZE (4096 / SPNIC_UINT32_BIT_SIZE) > +#define SPNIC_MAX_QUEUE_NUM 64 > > enum spnic_dev_status { > - SPNIC_DEV_INIT > + SPNIC_DEV_INIT, > + SPNIC_DEV_CLOSE, > + SPNIC_DEV_START, > + SPNIC_DEV_INTR_EN > }; > > #define SPNIC_DEV_NAME_LEN 32 > struct spnic_nic_dev { > + struct spnic_hwdev *hwdev; /* Hardware device */ > + > + struct spnic_txq **txqs; > + struct spnic_rxq **rxqs; > + struct rte_mempool *cpy_mpool; > + > + u16 num_sqs; > + u16 num_rqs; > + u16 max_sqs; > + u16 max_rqs; > + > + u16 rx_buff_len; > + u16 mtu_size; > + > + u16 rss_state; > + u8 num_rss; > + u8 rsvd0; > + > + u32 rx_mode; > + u8 rx_queue_list[SPNIC_MAX_QUEUE_NUM]; > + rte_spinlock_t queue_list_lock; > + pthread_mutex_t rx_mode_mutex; > + > + u32 default_cos; > + u32 rx_csum_en; > + > u32 dev_status; > + > + bool pause_set; > + pthread_mutex_t pause_mutuex; > + > + struct rte_ether_addr default_addr; > + struct rte_ether_addr *mc_list; > + > char dev_name[SPNIC_DEV_NAME_LEN]; > + u32 vfta[SPNIC_VFTA_SIZE]; /* VLAN bitmap */ > }; > > #define SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev) \