From: "lihuisong (C)" <lihuisong@huawei.com>
To: Yanling Song <songyl@ramaxel.com>, <dev@dpdk.org>
Cc: <yanling.song@linux.dev>, <yanggan@ramaxel.com>,
<xuyun@ramaxel.com>, <ferruh.yigit@intel.com>
Subject: Re: [PATCH v4 02/25] net/spnic: initialize the HW interface
Date: Tue, 28 Dec 2021 10:10:23 +0800 [thread overview]
Message-ID: <9a9afaaf-683a-37ae-251b-42abefb3e1d5@huawei.com> (raw)
In-Reply-To: <3029b106a8d95440f638874f3e8df0f89d61647b.1640426040.git.songyl@ramaxel.com>
在 2021/12/25 19:28, Yanling Song 写道:
> Add HW interface registers and initialize the HW
> interface.
>
> Signed-off-by: Yanling Song <songyl@ramaxel.com>
> ---
> 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 <rte_ether.h>
> +
> +#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 <rte_bus_pci.h>
> +#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 <rte_ether.h>
>
> #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) \
next prev parent reply other threads:[~2021-12-28 2:10 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-25 11:28 [PATCH v4 00/25] Net/SPNIC: support SPNIC into DPDK 22.03 Yanling Song
2021-12-25 11:28 ` [PATCH v4 01/25] drivers/net: introduce a new PMD driver Yanling Song
2021-12-25 11:28 ` [PATCH v4 02/25] net/spnic: initialize the HW interface Yanling Song
2021-12-28 2:10 ` lihuisong (C) [this message]
2021-12-29 11:49 ` Yanling Song
2021-12-25 11:28 ` [PATCH v4 03/25] net/spnic: add mbox message channel Yanling Song
2021-12-25 11:28 ` [PATCH v4 04/25] net/spnic: introduce event queue Yanling Song
2021-12-25 11:28 ` [PATCH v4 05/25] net/spnic: add mgmt module Yanling Song
2021-12-25 11:28 ` [PATCH v4 06/25] net/spnic: add cmdq and work queue Yanling Song
2021-12-25 11:28 ` [PATCH v4 07/25] net/spnic: add interface handling cmdq message Yanling Song
2021-12-25 11:28 ` [PATCH v4 08/25] net/spnic: add hardware info initialization Yanling Song
2021-12-25 11:28 ` [PATCH v4 09/25] net/spnic: support MAC and link event handling Yanling Song
2021-12-25 11:28 ` [PATCH v4 10/25] net/spnic: add function info initialization Yanling Song
2021-12-25 11:28 ` [PATCH v4 11/25] net/spnic: add queue pairs context initialization Yanling Song
2021-12-25 11:29 ` [PATCH v4 12/25] net/spnic: support mbuf handling of Tx/Rx Yanling Song
2021-12-25 11:29 ` [PATCH v4 13/25] net/spnic: support Rx congfiguration Yanling Song
2021-12-25 11:29 ` [PATCH v4 14/25] net/spnic: add port/vport enable Yanling Song
2021-12-25 11:29 ` [PATCH v4 15/25] net/spnic: support IO packets handling Yanling Song
2021-12-25 11:29 ` [PATCH v4 16/25] net/spnic: add device configure/version/info Yanling Song
2021-12-25 11:29 ` [PATCH v4 17/25] net/spnic: support RSS configuration update and get Yanling Song
2021-12-25 11:29 ` [PATCH v4 18/25] net/spnic: support VLAN filtering and offloading Yanling Song
2021-12-25 11:29 ` [PATCH v4 19/25] net/spnic: support promiscuous and allmulticast Rx modes Yanling Song
2021-12-25 11:29 ` [PATCH v4 20/25] net/spnic: support flow control Yanling Song
2021-12-25 11:29 ` [PATCH v4 21/25] net/spnic: support getting Tx/Rx queues info Yanling Song
2021-12-25 11:29 ` [PATCH v4 22/25] net/spnic: net/spnic: support xstats statistics Yanling Song
2021-12-25 11:29 ` [PATCH v4 23/25] net/spnic: support VFIO interrupt Yanling Song
2021-12-25 11:29 ` [PATCH v4 24/25] net/spnic: support Tx/Rx queue start/stop Yanling Song
2021-12-25 11:29 ` [PATCH v4 25/25] net/spnic: add doc infrastructure Yanling Song
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9a9afaaf-683a-37ae-251b-42abefb3e1d5@huawei.com \
--to=lihuisong@huawei.com \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@intel.com \
--cc=songyl@ramaxel.com \
--cc=xuyun@ramaxel.com \
--cc=yanggan@ramaxel.com \
--cc=yanling.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).